package com.ys.service.storage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.EditDto;
import com.ys.entity.base.CheckByGrid;
import com.ys.entity.base.TbFileInfo;
import com.ys.entity.base.TbSite;
import com.ys.entity.base.TpAmazonRegionItem;
import com.ys.entity.business.TpAmazonShop;
import com.ys.entity.storage.*;
import com.ys.entity.sys.TbStaticConfig;
import com.ys.entity.sys.TsUserChange;
import com.ys.enume.storage.TccFbaBoxUpEnum;
import com.ys.enume.storage.TccFbaBoxUpItemEnum;
import com.ys.enume.storage.TccFbaPlanEnum;
import com.ys.mapper.storage.*;
import com.ys.service.storage.FbaInboundApiService;
import com.ys.service.storage.TccFbaBoxUpService;
import com.ys.service.storage.TccFbaCancelService;
import com.ys.service.storage.TccFbaDeliverService;
import com.ys.service.sys.CommonApiService;
import com.ys.util.CheckUtil;
import com.ys.util.PdfUtil;
import com.ys.util.ToolUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.R;
import io.swagger.client.api.FbaInboundApi;
import io.swagger.client.model.Incentive;
import io.swagger.client.model.Item;
import io.swagger.client.model.ListShipmentItemsResponse;
import io.swagger.client.model.Shipment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

//FBA装箱单
@Service("tccFbaBoxUpService")
public class TccFbaBoxUpServiceImpl implements TccFbaBoxUpService {
	private static final Logger logger = LoggerFactory.getLogger(TccFbaBoxUpServiceImpl.class);

	@Autowired
	private TccFbaBoxUpMapper tccFbaBoxUpMapper;

	@Autowired
	private TccFbaBoxUpItemMapper tccFbaBoxUpItemMapper;

	@Autowired
	private TccFbaBoxMapper tccFbaBoxMapper;

	@Autowired
	private TccFbaBoxUpInfoMapper tccFbaBoxUpInfoMapper;

	@Autowired
	private TccFbaPlanMapper tccFbaPlanMapper;

	@Autowired
	private TccFbaBoxDetailMapper tccFbaBoxDetailMapper;

	@Autowired
	private TccFbaBoxUpPackMapper tccFbaBoxUpPackMapper;

	@Autowired
	private TccFbaBoxRelevanceMapper tccFbaBoxRelevanceMapper;


	@Autowired
	private CommonApiService<TccFbaBoxUp> commonApiService;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private StorageMapper storageMapper;

	@Autowired
	private FbaInboundApiService fbaInboundApiService;

	//@Autowired
	//private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;

	@Autowired
	private TccFbaDeliverService tccFbaDeliverService;

	@Autowired
	private TccFbaCancelService tccFbaCancelService;

	@Autowired
	private TccFbaPlanItemMapper tccFbaPlanItemMapper;

	private final ReentrantLock lock = new ReentrantLock();//同步锁



	/**
	 * 新增FBA装箱单（调用一次新增一个装箱单，以及对应子列表信息）
	 * @param boxUpemList 装箱单集合
	 * @param bidFbaPlan 计划单号
	 * @return 新增结果
	 */
	@Override
	//@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R addOneFbaBoxInfo(List<TccFbaBoxUpByAdd> boxUpemList, String bidFbaPlan)  throws Exception {
		logger.info(ShiroUtils.getUserId()+"新增FBA装箱单传参：bidFbaPlan="+bidFbaPlan+"；boxUpemList="+boxUpemList);
		//获取计划单信息
		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(bidFbaPlan).queryFirst();

		//int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
		//int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）
		int evenlyBoxNum = tccFbaPlan.getEvenlyBoxNum();//均分箱数

		//根据国家查询销售渠道信息
		TbSite tbSite  = new TbSite()
				//.addLeftJoin("TP_AmazonRegion B ON B.Code = A.RegionCode") //亚马逊 区域表
				//.addLeftJoin("TB_Site C ON C.RegionCode = A.RegionCode") //站点信息表
				.addLeftJoin("TP_AmazonShop D ON D.SiteId = A.Id") // 店铺信息表
				.addLeftJoin("TCC_Fbaplan E ON E.ShopId = D.Id") //FBA计划单
				.where("E.Bid = '"+bidFbaPlan+"'")
				.where("A.Status = 1")
				.queryFirst();
		if(tbSite == null || tbSite.getAmazonSalesChannel()==null){
			throw new IllegalArgumentException("未查询到店铺对应的国家销售渠道信息");
		}

		long userChangeId;
		//获取制单人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
		if(tsUserChange!=null){
			userChangeId = tsUserChange.getId();// 制单人变更信息
		}else {
			throw new IllegalArgumentException("未查询到制单人信息！");
		}

		int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
		int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）


		for(TccFbaBoxUpByAdd boxUpAddItem:boxUpemList){
			//获取单号信息
			String bid = commonApiService.getCommonNextBid(MenuId.TCC_FbaBoxUp);
			//填入母表信息
			TccFbaBoxUp entity = new TccFbaBoxUp()
					.setBid(bid)//单号
					.setCreateChangeId(userChangeId)//制单人
					.setBoxState(TccFbaBoxUpEnum.BoxState.NOT_UP.value)
					.setBidFbaPlan(bidFbaPlan)//计划单号
					.setBoxNum(0)//箱子数，初始0
					.setTagAllGoods(TccFbaBoxUpItemEnum.TagStateGoods.NOT.value)
					.setTagAllTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.NOT.value)
					.setTagAllEur(TccFbaBoxUpItemEnum.TagStateEur.NOT.value)
					.setStatus(1);

			//******** 按箱自动发货 ********
			if(deliverState==0){
				//获取、填入、新增包装组信息
				entity.setPackToken(boxUpAddItem.getFbaOrPackInfoList().get(0).getPackToken());
				entity.setPackId(boxUpAddItem.getFbaOrPackInfoList().get(0).getPackId());
			}else{
				//若方案选项标识符不为空
				if(checkUtil.isNotNullByObject(boxUpAddItem.getPlacementOptionId())){
					entity.setPlacementOptionId(boxUpAddItem.getPlacementOptionId());//填入方案选项标识符
				}
			}



			List<TccFbaBoxUpInfoByAdd> fbaOrPackInfoList = boxUpAddItem.getFbaOrPackInfoList();
			//遍历 包装组 或 FBA 信息
			for(TccFbaBoxUpInfoByAdd fbaOrPackItem:fbaOrPackInfoList){

				//获取商品信息
				List<TccFbaBoxUpItemByAdd> goodsInfoList = fbaOrPackItem.getGoodsInfoList();

				//******** 手动 ********
				if(creationMethod==0){

					//遍历子列表信息
					for(TccFbaBoxUpItemByAdd goodsItem:goodsInfoList){
						//获取计划单子表信息
						TccFbaPlanItem tccFbaPlanItem = new TccFbaPlanItem().setId(goodsItem.getFbaPlanItemId()).queryFirst();
						int numPlanDeliver = tccFbaPlanItem.getNumPlanDeliver(); //计划发货数量
						//int apiNum = tccFbaPlanItem.getNumApiDeliver(); //API发货数量
						//int averageBoxUpNum = evenlyBoxNum!=0 && creationMethod==1 ?apiNum/evenlyBoxNum:0;//均分装箱数量 = API发货数量 ÷ 均分箱数

						//填入子列表信息
						TccFbaBoxUpItem itemInfo = new TccFbaBoxUpItem()
								.setBidBoxUp(bid) //母表单号（TCC_FbaBoxUp）
								.setBidFbaPlan(bidFbaPlan) //FBA计划单号
								.setFbaPlanItemId(goodsItem.getFbaPlanItemId()) //Fba计划子件表id（TCC_FbaPlanItem）
								.setTagStateGoods(TccFbaBoxUpItemEnum.TagStateGoods.NOT.value) //商品标打印状态
								.setTagStateTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.NOT.value) //透明标打印状态
								.setTagStateEur(TccFbaBoxUpItemEnum.TagStateEur.NOT.value) //欧代标打印状态
								.setGoodsLink("https://www."+ tbSite.getAmazonSalesChannel().trim()+"/dp/"+goodsItem.getAsin()+"?ref=myi_title_dp") //商品链接
								.setStatus(1)
								.setPurchaseAmount(tccFbaPlanItem.getPriceIn()) //采购价
								.setAverageBoxUpNum(0) //均分装箱数量
								.setPlanBoxUpNum(numPlanDeliver) //计划发货数量
								;
						tccFbaBoxUpItemMapper.insert(itemInfo);
					}

				}
				//******** 自动 ********
				else {

					//******** 按箱自动发货 ********
					if(deliverState==0){


						List<TccFbaPlanItem> planItemList = new ArrayList<>();
						for(TccFbaBoxUpItemByAdd goodsItem:goodsInfoList){
							//获取计划单子表信息
							TccFbaPlanItem tccFbaPlanItem = new TccFbaPlanItem().setId(goodsItem.getFbaPlanItemId()).queryFirst();
							planItemList.add(tccFbaPlanItem);
						}


						List<TccFbaPlanItem> planItemListNew = new ArrayList<>();
						if(evenlyBoxNum>=5){
							Map<String, List<TccFbaPlanItem>> groupsBySku = planItemList.stream()
									.collect(Collectors.groupingBy(e->e.getSku()));

							//计算均分装箱数量
							List<TccFbaPlanItem> planItemListCountAfter = new ArrayList<>();
							//遍历，填入去重的信息
							groupsBySku.forEach((sku, listBySku) -> {

								logger.info("计算均分装箱数量：sku="+sku);
								int numApiDeliverTotal = 0;
								for(TccFbaPlanItem item : listBySku){
									numApiDeliverTotal = numApiDeliverTotal+item.getNumApiDeliver();
								}
								int boxUpNumTotal = numApiDeliverTotal/evenlyBoxNum;//总箱数
								logger.info("计算均分装箱数量：总箱数="+numApiDeliverTotal+"/"+evenlyBoxNum+"="+boxUpNumTotal);
								if(listBySku.size()==1){
									logger.info("计算均分装箱数量：SKU只有一条，均分装箱数量 = 总箱数="+boxUpNumTotal);
									TccFbaPlanItem tccFbaPlanItem = listBySku.get(0);
									tccFbaPlanItem.setNumApiDeliver(boxUpNumTotal);
									planItemListCountAfter.add(tccFbaPlanItem);
								}else{
									int boxUpNumEd = 0;
									for(int i=0;i< listBySku.size();i++){
										TccFbaPlanItem tccFbaPlanItem = listBySku.get(i);
										if(i!=listBySku.size()-1){
											int boxUpNum =  new BigDecimal(tccFbaPlanItem.getNumApiDeliver()).divide(new BigDecimal(evenlyBoxNum),0,BigDecimal.ROUND_HALF_UP).intValue();
											if(boxUpNum==0){
												boxUpNum = 1;
											}
											boxUpNumEd = boxUpNumEd+boxUpNum;
											tccFbaPlanItem.setNumApiDeliver(boxUpNum);
											logger.info("计算均分装箱数量：SKU多条，均分装箱数量 = "+tccFbaPlanItem.getNumApiDeliver() + "/" + evenlyBoxNum +"="+boxUpNum);
										}else {
											int boxUpNum = boxUpNumTotal - boxUpNumEd;
											tccFbaPlanItem.setNumApiDeliver(boxUpNum);
											logger.info("计算均分装箱数量：SKU多条（最后一条），均分装箱数量 = "+boxUpNumTotal + "-" + boxUpNumEd +"="+boxUpNum);
										}
										planItemListCountAfter.add(tccFbaPlanItem);
									}
								}
							});
							planItemListNew = planItemListCountAfter;
						}else{
							planItemListNew = planItemList;
						}

						//遍历子列表信息
						for(TccFbaPlanItem planItem:planItemListNew){

							int numPlanDeliver = planItem.getNumPlanDeliver(); //计划发货数量
							//int apiNum = planItem.getNumApiDeliver(); //API发货数量 =》 暂时用来存：均分装箱数量
							//int averageBoxUpNum = evenlyBoxNum!=0 && creationMethod==1 ? apiNum/evenlyBoxNum:0;//均分装箱数量 = API发货数量 ÷ 均分箱数
							int averageBoxUpNum =planItem.getNumApiDeliver();
							//填入子列表信息
							TccFbaBoxUpItem itemInfo = new TccFbaBoxUpItem()
									.setBidBoxUp(bid) //母表单号（TCC_FbaBoxUp）
									.setBidFbaPlan(bidFbaPlan) //FBA计划单号
									.setFbaPlanItemId(planItem.getId()) //Fba计划子件表id（TCC_FbaPlanItem）
									.setTagStateGoods(TccFbaBoxUpItemEnum.TagStateGoods.NOT.value) //商品标打印状态
									.setTagStateTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.NOT.value) //透明标打印状态
									.setTagStateEur(TccFbaBoxUpItemEnum.TagStateEur.NOT.value) //欧代标打印状态
									.setGoodsLink("https://www."+ tbSite.getAmazonSalesChannel().trim()+"/dp/"+planItem.getAsin()+"?ref=myi_title_dp") //商品链接
									.setStatus(1)
									.setPurchaseAmount(planItem.getPriceIn()) //采购价
									.setAverageBoxUpNum(evenlyBoxNum>=5?averageBoxUpNum:0) //均分装箱数量
									.setPlanBoxUpNum(numPlanDeliver) //计划发货数量
									;
							tccFbaBoxUpItemMapper.insert(itemInfo);
						}

					}
					//******** 按SKU自动发货 ********
					else{

						//获取、填入、新增FBA信息
						TccFbaBoxUpInfo tccFbaBoxUpInfo = new TccFbaBoxUpInfo()
								.setBoxUpBid(bid)//母表单号（TCC_FbaBoxUp）
								.setFbaNo(fbaOrPackItem.getFbaNo())//FBA编号
								.setFbaTrackNo(fbaOrPackItem.getFbaTrackNo())//FBA追踪编号
								.setFbaToken(fbaOrPackItem.getFbaToken())//FBAtoken和id字段
								.setFbaId(fbaOrPackItem.getFbaId())
								.setFbaWarehouse(fbaOrPackItem.getFbaWarehouse())//FBA仓库
								.setFbaWarehouseAddr(fbaOrPackItem.getFbaWarehouseAddr())//FBA仓库地址(目的地)
								.setFbaAmount(fbaOrPackItem.getFbaAmount())//FBA费用
								.setSearchIsShow(1)//查询页是否展示
								.setBidFbaPlan(tccFbaPlan.getBid())//计划单号
								.setStatus(1);
						tccFbaBoxUpInfoMapper.insert(tccFbaBoxUpInfo);
						//遍历子列表信息
						for(TccFbaBoxUpItemByAdd goodsItem:goodsInfoList){
							//获取计划单子表信息
							TccFbaPlanItem tccFbaPlanItem = new TccFbaPlanItem().setId(goodsItem.getFbaPlanItemId()).queryFirst();
							//int numPlanDeliver = tccFbaPlanItem.getNumPlanDeliver(); //计划发货数量
							//int apiNum = tccFbaPlanItem.getNumApiDeliver(); //API发货数量
							//int averageBoxUpNum = evenlyBoxNum!=0 && creationMethod==1 ?apiNum/evenlyBoxNum:0;//均分装箱数量 = API发货数量 ÷ 均分箱数

							//填入子列表信息
							TccFbaBoxUpItem itemInfo = new TccFbaBoxUpItem()
									.setBidBoxUp(bid) //母表单号（TCC_FbaBoxUp）
									.setBidFbaPlan(bidFbaPlan) //FBA计划单号
									.setFbaPlanItemId(goodsItem.getFbaPlanItemId()) //Fba计划子件表id（TCC_FbaPlanItem）
									.setTagStateGoods(TccFbaBoxUpItemEnum.TagStateGoods.NOT.value) //商品标打印状态
									.setTagStateTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.NOT.value) //透明标打印状态
									.setTagStateEur(TccFbaBoxUpItemEnum.TagStateEur.NOT.value) //欧代标打印状态
									.setGoodsLink("https://www."+ tbSite.getAmazonSalesChannel().trim()+"/dp/"+goodsItem.getAsin()+"?ref=myi_title_dp") //商品链接
									.setStatus(1)
									.setPurchaseAmount(tccFbaPlanItem.getPriceIn()) //采购价
									.setAverageBoxUpNum(0) //均分装箱数量
									.setPlanBoxUpNum(goodsItem.getBoxUpNum()) //拆分后的数量
									;
							tccFbaBoxUpItemMapper.insert(itemInfo);

							//新增FBA关联表信息
							TccFbaBoxRelevance tccFbaBoxRelevance = new TccFbaBoxRelevance()
									.setBoxUpItemId(itemInfo.getId())//装箱单子列表id（商品）（TCC_FbaBoxUpItem）
									.setRelevanceType(2)//关联类型（1其他、2关联商品、3关联箱子、4关联装箱详情）
									.setFbaBoxInfoId(tccFbaBoxUpInfo.getId())//装箱单FBA信息表id
									.setRemark(bid)//备注
									.setStatus(1);
							tccFbaBoxRelevanceMapper.insert(tccFbaBoxRelevance);
						}
					}
				}
			}

			entity.setApiCount(0);
			//新增装箱单母表信息
			tccFbaBoxUpMapper.insert(entity);


			//修改标签打印状态
            List<TccFbaBoxUpItem> tccFbaBoxUpItemList = new TccFbaBoxUpItem().setBidBoxUp(bid).queryList();
            for(TccFbaBoxUpItem itemInfo:tccFbaBoxUpItemList){
                //不需要打印的标签也修改成已打印
                TccFbaPlanItem tccFbaPlanItem = new TccFbaPlanItem().setId(itemInfo.getFbaPlanItemId()).queryFirst();
                if(tccFbaPlanItem.getNumPlanDeliver()<=0){//计划发货数量<=0
                    itemInfo.setTagStateGoods(TccFbaBoxUpItemEnum.TagStateGoods.YES.value);
                }
                if(tccFbaPlanItem.getIsSign().equals("否")|| checkUtil.isNullByObject(tccFbaPlanItem.getAnnexFile())){//透明标记(是/否 = 否
                    itemInfo.setTagStateTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.YES.value);
                }

                TpAmazonShop tpAmazonShop = new TpAmazonShop().setId(tccFbaPlan.getShopId()).queryFirst();
                if(tpAmazonShop!=null && tpAmazonShop.getEuStatus()!=null && tpAmazonShop.getEuStatus()==0){
                    itemInfo.setTagStateEur(TccFbaBoxUpItemEnum.TagStateEur.YES.value);
                }
                tccFbaBoxUpItemMapper.update(itemInfo);
            }


		}
		return R.ok("操作成功");
	}


	/**
	 * 修改配货清单号，根据计划单号
	 * @param infolist 列表
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R updateDistributionBid(List<Map<String, Object>> infolist) throws Exception{

		//获取装箱单号列表信息、拼接计划单号
		List<String> bidList = new ArrayList<>();
		String bids = "";
		for(Map<String, Object> infoItem:infolist){
			String bid = infoItem.get("bid").toString();
			bidList.add(bid);
			if("".equals(bids)){
				bids = "'"+bid+"'";
			}else{
				bids = bids+",'"+bid+"'";
			}
		}

		//获取配货清单号
		String distributionBid = commonApiService.getCommonNextBid(MenuId.TCC_FbaBoxUp_QD);

		List<PdfUtil.PeihuoDto.ItemDto> itemArr = new ArrayList<>();

		List<TccFbaBoxUp> tccFbaBoxUpList = new TccFbaBoxUp().where("A.Bid IN ("+bids+")").queryList();
		//获取 装箱单子列表信息
		List<TccFbaBoxUpItem> boxUpItemList = new TccFbaBoxUpItem()
				.addLeftJoin("TCC_FbaPlanItem B ON B.Id = A.FbaPlanItemId")
				.setOrderby("B.Sku ASC")
				.where("A.BidBoxUp IN ("+bids+")")
				.queryList();

		for(TccFbaBoxUp tccFbaBoxUp:tccFbaBoxUpList){
			TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
			TpAmazonShop tpAmazonShop = new TpAmazonShop().setId(tccFbaPlan.getShopId()).queryFirst();
			//获取 FBA物流方式维护表 信息
			TccFbaLogisticsMethod tccFbaLogisticsMethod = new TccFbaLogisticsMethod().setSourceBid(tccFbaBoxUp.getBidFbaPlan()).setSourceType(0).queryFirst();
			List<TccFbaPlanItem> tccFbaPlanItemListByPbid = new TccFbaPlanItem().setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan()).setOrderby("A.sku").queryList();
			List<TccFbaBoxUpItem> boxUpItemListByPlanbid = boxUpItemList.stream().filter(e->e.getBidFbaPlan().equals(tccFbaBoxUp.getBidFbaPlan())).collect(Collectors.toList());

			String codeBid = tccFbaBoxUp.getBidFbaPlan()+"/"+tccFbaBoxUp.getBid();//单号
			String codeCompany = tccFbaPlan.getVgsbm();//公司编码
			String nameCompany = tccFbaPlan.getVgsJc();//公司简称
			String nameWLFS = tccFbaLogisticsMethod.getLogsticsWay();//物流服务名称

			//计算重量
//			BigDecimal weightPredictNum = BigDecimal.ZERO;
//			for(TccFbaPlanItem tccFbaPlanItem:tccFbaPlanItemListByPbid){
//				if(tccFbaPlanItem.getWeightPackage()!=null){
//					weightPredictNum = weightPredictNum.add(tccFbaPlanItem.getWeightPackage().divide(new BigDecimal(1000),2,BigDecimal.ROUND_HALF_UP));//克转千克保留2位小数，四舍五入
//				}
//			}
			TccFbaFeeDetails tccFbaFeeDetails = new TccFbaFeeDetails().setSourceBid(tccFbaPlan.getBid()).queryFirst();

			String weightPredict = tccFbaFeeDetails.getWeightReal().toString()+"kg";
			String remark = tccFbaPlan.getRemark();//备注
			String creationMethod = tccFbaPlan.getCreationMethod()==0?"手动":"自动";//货件创建方式
			String averageBoxUpNum = "";//均分装箱数量
			String isOd = tpAmazonShop.getEuStatus() == 1? "是":"否"; // 是否欧代标
			List<PdfUtil.PeihuoDto.ItemDto.RowDto> rows = new ArrayList<PdfUtil.PeihuoDto.ItemDto.RowDto>();

			for(TccFbaBoxUpItem tccFbaBoxUpItem:boxUpItemListByPlanbid){
//				//汇总均分装箱数量
//				if("".equals(averageBoxUpNum)){
//					averageBoxUpNum = tccFbaBoxUpItem.getAverageBoxUpNum().toString();
//				}else {
//					averageBoxUpNum = averageBoxUpNum + "/" + tccFbaBoxUpItem.getAverageBoxUpNum().toString();
//				}
				averageBoxUpNum = tccFbaPlan.getEvenlyBoxNum().toString(); // 箱子数量

				TccFbaPlanItem tccFbaPlanItem = tccFbaPlanItemListByPbid.stream().filter(e->e.getId().equals(tccFbaBoxUpItem.getFbaPlanItemId())).collect(Collectors.toList()).get(0);

				String codeGoods = tccFbaPlanItem.getCommodityCode();// 商品编码
				String nameGoods = tccFbaPlanItem.getCommodityName(); // 商品名称
				String fnsku = tccFbaPlanItem.getFnSku(); // FNSKU
				String numPlanDeliver = tccFbaPlanItem.getNumPlanDeliver().toString(); // 计划发货数量
				String numAverageDeliver = tccFbaBoxUpItem.getAverageBoxUpNum().toString(); // 均分装箱数量
				String locationGoods = tccFbaPlanItem.getVhw(); // 货位
				String locationStock = tccFbaPlanItem.getVkq(); // 库区
				String locationName = tccFbaPlanItem.getVck(); // 仓库名
				String imgGoods = tccFbaPlanItem.getImg(); // 商品图片
				String numStockLeft = (tccFbaPlanItem.getNumStock() - tccFbaPlanItem.getNumPlanDeliver()) + ""; // 剩余库存
				String signName = tccFbaPlanItem.getSignCode(); // 透明标记（是/否）
				rows.add(new PdfUtil.PeihuoDto.ItemDto.RowDto(
						codeGoods,
						nameGoods,
						fnsku,
						numPlanDeliver,
						numAverageDeliver,
						locationGoods,
						locationStock,
						locationName,
						imgGoods,
						numStockLeft,
						signName
				));
			}



			PdfUtil.PeihuoDto.ItemDto itemDto = new PdfUtil.PeihuoDto.ItemDto(codeBid, codeCompany, weightPredict, nameCompany, nameWLFS, averageBoxUpNum,remark, creationMethod, isOd,rows);
			itemArr.add(itemDto);
		}

		PdfUtil.PeihuoDto dto = new PdfUtil.PeihuoDto(itemArr);
		String resUrl = PdfUtil.generatePeiHuo(distributionBid, dto);


		//批量修改清单号、已配货状态
		storageMapper.updateFbaBoxUpDistributionBid(bidList,distributionBid);
		//修改未配货状态的装箱单信息，已装箱的状态不修改
		storageMapper.updateFbaBoxUpBoxState(bidList,TccFbaBoxUpEnum.BoxState.YES_DIS.value);
		return R.ok(resUrl);
	}


	/**
	 * 获取箱规编辑页信息
	 * @param bid 单号
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public TccFbaBoxUpBoxRoleEdit getBoxRoleEditInfo(String bid) throws Exception{
		logger.info(ShiroUtils.getUserId()+"获取箱规编辑页信息"+bid+"；");


		TbStaticConfig tbStaticConfigByWl = new TbStaticConfig().setKeyOne("TCC_FbaBoxUp").setKeyTwo("throwingWeightWl").queryFirst();
		TbStaticConfig tbStaticConfigByKd = new TbStaticConfig().setKeyOne("TCC_FbaBoxUp").setKeyTwo("throwingWeightKd").queryFirst();


		String tipMsg = "";
		int isEdit = 1;
		int boxNumMax = 0;

		//获取装箱单母表信息
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		TbStaticConfig tbStaticConfig = new TbStaticConfig().setKeyOne("TCC_FbaBoxUp").setKeyTwo("boxNumMax").queryFirst();

		//获取其他装箱表单信息
		//装箱单子列表
		List<Map<String,Object>> boxUpItemList = new TccFbaBoxUpItem()
				.addLeftJoin("TCC_FbaPlanItem B ON A.FbaPlanItemId = B.Id")//Fba计划子件表
				.addField("B.CommodityCode AS commodityCode")//商品编码
				.addField("B.CommodityName AS commodityName")//商品名称
				.addField("B.Sku AS sku")//Sku
				.addField("B.FnSku AS fnSku")//FnSku
				.addField("ISNULL(A.PlanBoxUpNum,0) AS boxUpNum")//装箱数量

				.setBidBoxUp(bid)
				.setOrderby("B.Sku")//按sku升序
				.queryMap();

		//装箱单箱子信息表 列表
		List<TccFbaBox> boxList = new TccFbaBox().setBidBoxUp(bid).setOrderby("A.BoxNo").queryList();
		//装箱单装箱详情信息表 列表
		List<TccFbaBoxDetail> boxDetailList = new TccFbaBoxDetail().setBidBoxUp(bid).queryList();

		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
		int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
		int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）

		int boxNum = boxList.size();
		//验证状态，已取消、已审核的不能编辑
		if(tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_CANCEL.value)
				|| tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_PASS.value) ){
			tipMsg = "该货件"+TccFbaBoxUpEnum.BoxState.getName(tccFbaBoxUp.getBoxState())+"，无法进行箱规编辑；";
			isEdit = 0;
		}
		if(checkUtil.isNotNullByObject(tccFbaBoxUp.getPlacementOptionId())){
			tipMsg = "该货件已经选择好方案，无法进行箱规编辑；";
			isEdit = 0;
		}

		//验证，如果是手动，并且进行了FBA导入（按箱），也不能编辑
		int isFbaImportByBox = new TccFbaBoxRelevance().setRemark(tccFbaBoxUp.getBid()).where("A.BoxId IS NOT NULL").count();
		if(isEdit!=0 && creationMethod==0 && isFbaImportByBox>0){
			tipMsg = "该货件进行了\"FBA导入（按箱）\"，无法进行箱规编辑；";
			isEdit = 0;
		}

		StringBuilder printTip = new StringBuilder();
		//***标签未打印无法编辑箱规
		if(boxUpItemList!=null && boxUpItemList.size()>0) {
			for (Map<String, Object> item : boxUpItemList) {
				StringBuilder printTipByRow = new StringBuilder();
				if(Integer.parseInt(item.get("tagStateGoods").toString())==0){
					printTipByRow.append("商品标签");
				}
				if(Integer.parseInt(item.get("tagStateTransparent").toString())==0){
					if(printTip.length()>0) printTipByRow.append("、");
					printTipByRow.append("透明标签");
				}
				if(Integer.parseInt(item.get("tagStateEur").toString())==0){
					if(printTip.length()>0) printTipByRow.append("、");
					printTipByRow.append("欧代标签");
				}
				if(printTipByRow.length()>0){
					printTipByRow = new StringBuilder().append("商品编码【").append(item.get("commodityCode").toString()).append("】").append(printTipByRow).append("未打印；</br>");
					printTip.append(printTipByRow);
				}
			}
		}

		if(printTip.length()>0){
			printTip = new StringBuilder().append("温馨提示：</br>").append(printTip);
		}


		//获取最大箱子数量
		if(tbStaticConfig!=null && tbStaticConfig.getName()!=null){
			boxNumMax = Integer.parseInt(tbStaticConfig.getName());
		}

		int boxNumIsEdit;//箱子数量是否可编辑 0否、1是
		if(creationMethod == 1 && tccFbaPlan.getEvenlyBoxNum()!=0){// 下单方式：自动 &&  均分箱数！=0
			boxNumIsEdit = 0;//箱子数量不可编辑
			boxNum = tccFbaPlan.getEvenlyBoxNum();//箱子数量 = 均分箱数
		}else {
			boxNumIsEdit = 1;//箱子数量可编辑
		}

		int boxNumIsZero = 0;
		if(boxNum==0){
			boxNum = 1;
			boxNumIsZero = 1;
		}

		TccFbaBoxUpBoxRoleEdit tccFbaBoxUpBoxRoleEdit = new TccFbaBoxUpBoxRoleEdit();
		if(tccFbaBoxUp.getBoxUpChangeId()!=null){
			TsUserChange tsUserChange = new TsUserChange().setId(tccFbaBoxUp.getBoxUpChangeId()).queryFirst();
			tccFbaBoxUpBoxRoleEdit.setUserId(tsUserChange.getUserId());//装箱人工号
			tccFbaBoxUpBoxRoleEdit.setUserName(tsUserChange.getUserName());//装箱人姓名
		}
		tccFbaBoxUpBoxRoleEdit.setIsEdit(isEdit);//是否可编辑 0否、1是
		tccFbaBoxUpBoxRoleEdit.setBid(bid);//单号
		tccFbaBoxUpBoxRoleEdit.setTipMsg(tipMsg);//提示信息

		tccFbaBoxUpBoxRoleEdit.setPrintTip(printTip.toString());

		tccFbaBoxUpBoxRoleEdit.setBoxNumMax(boxNumMax);//最大箱子数量
		tccFbaBoxUpBoxRoleEdit.setBoxNum(boxNum);//箱子数量
		tccFbaBoxUpBoxRoleEdit.setBoxNumIsEdit(boxNumIsEdit);//箱子数量是否可编辑 0否、1是

		List<Map<String,Object>> dataList = new ArrayList<>();//头部列表数据
		List<Map<String,Object>> dataListByBox = new ArrayList<>();//箱子信息

		//填入 头部列表数据
		if(boxUpItemList!=null && boxUpItemList.size()>0){

			for(Map<String,Object> item:boxUpItemList){
				long itemId = Long.parseLong(item.get("id").toString());
				Map<String,Object> dataInfo = new HashMap<>();
				dataInfo.put("fbaBoxUpItemId",item.get("id"));//装箱单子列表id
				dataInfo.put("commodityCode",item.get("commodityCode"));//商品编码
				dataInfo.put("commodityName",item.get("commodityName"));//商品名称
				dataInfo.put("sku",item.get("sku"));//sku
				dataInfo.put("fnSku",item.get("fnSku"));//fnSku
				dataInfo.put("boxUpNum",item.get("boxUpNum"));//包装组数量
				dataInfo.put("averageBoxUpNum",item.get("averageBoxUpNum"));//均分装箱数量
				dataInfo.put("purchaseAmount",item.get("purchaseAmount"));//采购价
				dataInfo.put("realityBoxUpNum",item.get("realityBoxUpNum")!=null?item.get("realityBoxUpNum"):"");//实际装箱数量
				dataInfo.put("numOrWeight","num");//装箱数量数据 OR 重量数据

				if(boxList!=null && boxList.size()>0){
					for(TccFbaBox boxInfo : boxList){
						long boxId = boxInfo.getId();
						List<TccFbaBoxDetail> boxDetailListByBoxAndItem = boxDetailList.stream()
								.filter(e->e.getBoxId() == boxId && e.getBoxUpItemId() == itemId)
								.collect(Collectors.toList());
						if(boxDetailListByBoxAndItem.size()>0){
							dataInfo.put("box"+boxInfo.getBoxNo(),boxDetailListByBoxAndItem.get(0).getNum());//对应箱子数量
						}else {
							dataInfo.put("box"+boxInfo.getBoxNo(),0);//对应箱子数量
						}
					}
				}else {
					if(boxNum!=0){
						for(int i=1;i<=boxNum;i++){
							dataInfo.put("box"+i,"");//对应箱子重量
						}
					}
				}
				dataList.add(dataInfo);
			}


			//空行
			Map<String,Object> dataInfoByBlank = new HashMap<>();
			dataInfoByBlank.put("fnSku","总计");
			dataInfoByBlank.put("numOrWeight",0);
			if(boxList!=null && boxList.size()>0){
				for(TccFbaBox boxInfo : boxList){
					long boxId = boxInfo.getId();
					int boxNumTotal = 0;
					List<TccFbaBoxDetail> boxDetailListByBoxAndItem = boxDetailList.stream()
							.filter(e->e.getBoxId() == boxId)
							.collect(Collectors.toList());

					if(boxDetailListByBoxAndItem.size()>0){
						for(TccFbaBoxDetail tccFbaBoxDetail:boxDetailListByBoxAndItem){
							boxNumTotal = boxNumTotal + tccFbaBoxDetail.getNum();
						}
					}
					dataInfoByBlank.put("box"+boxInfo.getBoxNo(),boxNumTotal);//对应箱子数量总计
				}
			}else {
				if(boxNum!=0){
					for(int i=1;i<=boxNum;i++){
						dataInfoByBlank.put("box"+i,0);//对应箱子数量总计
					}
				}
			}
			//获取总计数据
			if(dataList!=null && dataList.size()>0) {

				int boxUpNumTotal = 0;//总计：包装组数量
				int averageBoxUpNumTotal = 0;//总计：均分装箱数量
				BigDecimal purchaseAmountTotal = BigDecimal.ZERO;//总计：采购单价
				int realityBoxUpNumTotal = 0;//总计：数量总计
				for (Map<String, Object> item : dataList) {
					if(item.get("boxUpNum")!=null && !"".equals(item.get("boxUpNum")))boxUpNumTotal = boxUpNumTotal + Integer.parseInt(item.get("boxUpNum").toString());//包装组数量
					if(item.get("averageBoxUpNum")!=null && !"".equals(item.get("averageBoxUpNum")))averageBoxUpNumTotal = averageBoxUpNumTotal + Integer.parseInt(item.get("averageBoxUpNum").toString());//均分装箱数量
					if(item.get("purchaseAmount")!=null && !"".equals(item.get("purchaseAmount")))purchaseAmountTotal = purchaseAmountTotal.add(new BigDecimal(item.get("purchaseAmount").toString()));//采购价
					if(item.get("realityBoxUpNum")!=null && !"".equals(item.get("realityBoxUpNum")))realityBoxUpNumTotal = realityBoxUpNumTotal + Integer.parseInt(item.get("realityBoxUpNum").toString());//实际装箱数量
				}
				dataInfoByBlank.put("boxUpNum",boxUpNumTotal);//包装组数量
				dataInfoByBlank.put("averageBoxUpNum",averageBoxUpNumTotal);//均分装箱数量
				//dataInfoByBlank.put("purchaseAmount",purchaseAmountTotal);//采购价
				dataInfoByBlank.put("realityBoxUpNum",realityBoxUpNumTotal);//实际装箱数量
			}

			dataList.add(dataInfoByBlank);
			//new 填入重量
			Map<String,Object> dataInfoByTable1 = new HashMap<>();
			dataInfoByTable1.put("realityBoxUpNum","重量（kg）");
			dataInfoByTable1.put("numOrWeight","weight");//装箱数量数据 OR 重量数据
			if(boxList!=null && boxList.size()>0){
				for(TccFbaBox boxInfo : boxList){
					dataInfoByTable1.put("box"+boxInfo.getBoxNo(),boxInfo.getBoxWeight());//对应箱子重量
					dataInfoByTable1.put("USAbox"+boxInfo.getBoxNo(),boxInfo.getBoxWeight().multiply(new BigDecimal(2.205)).setScale(2, BigDecimal.ROUND_HALF_UP));//对应箱子重量
				}
			}else {
				if(boxNum!=0){
					for(int i=1;i<=boxNum;i++){
						dataInfoByTable1.put("box"+i,"");//对应箱子重量
					}
				}
			}

			dataList.add(dataInfoByTable1);

		}

		//填入 箱子信息
		if(boxList!=null && boxList.size()>0){
			//根据 长宽高重量 去重
			Map<String, List<TccFbaBox>> boxListByGroup = boxList.stream()
					.collect(Collectors.groupingBy(
							e->e.getBoxLong() + "*"
									+ e.getBoxWide() + "*"
									+ e.getBoxHigh() + "*"
									//+ e.getBoxWeight()//old 重量
					));
			List<TccFbaBox> groupAfterList = new ArrayList<>();
			//遍历，填入去重的信息
			boxListByGroup.forEach((k, v) -> groupAfterList.add(v.get(0)));
			if(groupAfterList.size()>0){

				//按箱子编号升序
				List<TccFbaBox> sortAfterList = groupAfterList.stream()
						.sorted(Comparator.comparing(TccFbaBox::getBoxNo))
						.collect(Collectors.toList());

				for(TccFbaBox boxInfo : sortAfterList){
					Map<String,Object> dataInfo = new HashMap<>();
					dataInfo.put("boxLong",boxInfo.getBoxLong());//长
					dataInfo.put("boxWide",boxInfo.getBoxWide());//宽
					dataInfo.put("boxHigh",boxInfo.getBoxHigh());//高
					dataInfo.put("USAboxLong",boxInfo.getBoxLong().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP));//长
					dataInfo.put("USAboxWide",boxInfo.getBoxWide().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP));//宽
					dataInfo.put("USAboxHigh",boxInfo.getBoxHigh().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP));//高
					//dataInfo.put("boxWeight",boxInfo.getBoxWeight());//old 重量

					BigDecimal throwingWeightWl = (boxInfo.getBoxLong().multiply(boxInfo.getBoxWide()).multiply(boxInfo.getBoxHigh()))
							.divide(new BigDecimal(tbStaticConfigByWl.getName()),2,BigDecimal.ROUND_HALF_UP);//抛重-物流

					BigDecimal throwingWeightKd = (boxInfo.getBoxLong().multiply(boxInfo.getBoxWide()).multiply(boxInfo.getBoxHigh()))
							.divide(new BigDecimal(tbStaticConfigByKd.getName()),2,BigDecimal.ROUND_HALF_UP);//抛重-快递

					dataInfo.put("throwingWeight",throwingWeightWl+" / "+throwingWeightKd);

					for(TccFbaBox boxCheckedInfo : boxList){
						int ischecked = 0;
						if(boxCheckedInfo.getBoxLong().compareTo(boxInfo.getBoxLong())==0
								&& boxCheckedInfo.getBoxWide().compareTo(boxInfo.getBoxWide())==0
								&& boxCheckedInfo.getBoxHigh().compareTo(boxInfo.getBoxHigh())==0
								//&& boxCheckedInfo.getBoxWeight().compareTo(boxInfo.getBoxWeight())==0//old 重量
						){
							ischecked = 1;
						}
						dataInfo.put("box"+boxCheckedInfo.getBoxNo(),ischecked);//对应箱子是否勾选相应的尺寸配置
					}
					dataListByBox.add(dataInfo);


				}
			}
		}else{
			if(boxNumIsZero==1){
				Map<String,Object> dataInfo = new HashMap<>();
				dataInfo.put("box1",0);
				dataListByBox.add(dataInfo);
			}
		}
		tccFbaBoxUpBoxRoleEdit.setDataList(dataList);
		tccFbaBoxUpBoxRoleEdit.setDataListByBox(dataListByBox);
		return tccFbaBoxUpBoxRoleEdit;

	}


	/**
	 * 箱规编辑保存
	 * @param params 需要保存的信息
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R saveBoxRoleEditInfo(Map<String, Object> params) throws Exception{
		logger.info(ShiroUtils.getUserId()+"箱规编辑保存参数:"+params);
		//参数验证
		R checkParamsRes = checkBoxRoleEditInfo(params);
		if(checkParamsRes.getCode().equals(R.Code.FAILED.value)){
			//验证不通过
			return checkParamsRes;
		}
		TccFbaBoxUpBoxRoleEdit editInifo = (TccFbaBoxUpBoxRoleEdit) checkParamsRes.get("data");
		//删除原数据
		//删除装箱单箱子信息表 根据bid
		storageMapper.deleteTccFbaBoxByBid(editInifo.getBid());
		//删除装箱单装箱详情信息表 根据bid
		storageMapper.deleteTccFbaBoxDetailByBid(editInifo.getBid());

		int boxNum = editInifo.getBoxNum();//装箱数量
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(editInifo.getBid()).queryFirst();

		List<TccFbaBoxDetail> detailList = new ArrayList<>();

		//获取箱子信息 表1
		List<Map<String,Object>> dataList = editInifo.getDataList();
		List<Map<String,Object>> dataListByWeight = dataList.stream().filter(e->e.get("numOrWeight").toString().equals("weight")).collect(Collectors.toList());

		//遍历 并新增
		for(int i=1;i<=boxNum;i++){
			TccFbaBox tccFbaBox = new TccFbaBox();
			tccFbaBox.setBidBoxUp(editInifo.getBid());//装箱单号（TCC_FbaBoxUp）
			tccFbaBox.setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan());//计划单号
			tccFbaBox.setBoxNo(i);//箱子编号
			tccFbaBox.setStatus(1);
			//获取箱子信息 表2
			List<Map<String,Object>> dataListByBox = editInifo.getDataListByBox();
			for(Map<String,Object> boxItem:dataListByBox){
				if(boxItem.get("box"+i)!=null && Integer.parseInt(boxItem.get("box"+i).toString())==1){
					tccFbaBox.setBoxLong(new BigDecimal(boxItem.get("boxLong").toString()));
					tccFbaBox.setBoxWide(new BigDecimal(boxItem.get("boxWide").toString()));
					tccFbaBox.setBoxHigh(new BigDecimal(boxItem.get("boxHigh").toString()));
					//tccFbaBox.setBoxWeight(new BigDecimal(boxItem.get("boxWeight").toString()));
					tccFbaBox.setBoxWeight(new BigDecimal(dataListByWeight.get(0).get("box"+i).toString()));
				}
			}
			tccFbaBoxMapper.insert(tccFbaBox);

			List<Map<String,Object>> dataListByNum = dataList.stream().filter(e->e.get("numOrWeight").toString().equals("num")).collect(Collectors.toList());
			for (Map<String,Object> boxNumItem:dataListByNum) {
			//for(Map<String,Object> boxNumItem:dataList){
				//非空 且 >0 ， 则新增
				if(checkUtil.isNotNullByObject(boxNumItem.get("box"+i)) && new BigDecimal(boxNumItem.get("box"+i).toString()).compareTo(BigDecimal.ZERO)>0){
					TccFbaBoxDetail tccFbaBoxDetail = new TccFbaBoxDetail();
					tccFbaBoxDetail.setBoxId(tccFbaBox.getId());//箱子表id（TCC_FbaBox）
					tccFbaBoxDetail.setBidBoxUp(editInifo.getBid());//装箱单号（TCC_FbaBoxUp）
					tccFbaBoxDetail.setStatus(1);
					tccFbaBoxDetail.setBoxUpItemId(Long.parseLong(boxNumItem.get("fbaBoxUpItemId").toString()));//装箱单子列表id（TCC_FbaBoxUpItem）
					tccFbaBoxDetail.setNum(Integer.parseInt(boxNumItem.get("box"+i).toString()));
					tccFbaBoxDetail.setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan());//计划单号
					tccFbaBoxDetailMapper.insert(tccFbaBoxDetail);
					detailList.add(tccFbaBoxDetail);
				}
			}
		}

		//修改装箱人
		//TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(editInifo.getBid()).queryFirst();
		//保存箱子数量
		tccFbaBoxUp.setBoxNum(Integer.parseInt(params.get("boxNum").toString()));
		//获取装箱人信息
		TsUserChange tsUserChange = new TsUserChange().setUserId(editInifo.getUserId()).setStatus(1).queryFirst();
		if(tccFbaBoxUp!=null && tsUserChange!=null) {
			tccFbaBoxUp.setBoxUpChangeId(tsUserChange.getId());//装箱人变更信息
			tccFbaBoxUp.setBoxState(TccFbaBoxUpEnum.BoxState.YES_UP.value);//已装箱
			tccFbaBoxUpMapper.update(tccFbaBoxUp);
		}

		//更新装箱实际数量
		List<TccFbaBoxUpItem> itemList = new TccFbaBoxUpItem().setBidBoxUp(editInifo.getBid()).queryList();
		for(TccFbaBoxUpItem tccFbaBoxUpItem:itemList){
			List<TccFbaBoxDetail> itemDetailList = detailList.stream().filter(e->e.getBoxUpItemId().equals(tccFbaBoxUpItem.getId())).collect(Collectors.toList());
			//new TccFbaBoxDetail().setBoxUpItemId(tccFbaBoxUpItem.getId()).queryList();
			int realityBoxUpNum = 0;
			for(TccFbaBoxDetail detailItem:itemDetailList){
				realityBoxUpNum = realityBoxUpNum + detailItem.getNum();
			}
			tccFbaBoxUpItem.setRealityBoxUpNum(realityBoxUpNum);
			tccFbaBoxUpItemMapper.update(tccFbaBoxUpItem);
		}

		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
		int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
		int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）

		//关联 商品装箱详情信息 与 FBA
		List<TccFbaBoxUpInfo> fbaInfoList = new TccFbaBoxUpInfo().setBoxUpBid(editInifo.getBid()).queryList();
		if(fbaInfoList!=null && fbaInfoList.size()>0){
			if(creationMethod == 0){//手动
				for(TccFbaBoxDetail detailItem:detailList){
					detailItem.setFbaBoxUpInfoId(fbaInfoList.get(0).getId());
					tccFbaBoxDetailMapper.update(detailItem);
				}
			}else {
				//自动
				if(deliverState == 1){//1按SKU自动发货
					for(TccFbaBoxDetail detailItem:detailList){
						TccFbaBoxRelevance relevanceInfo = new TccFbaBoxRelevance().setBoxUpItemId(detailItem.getBoxUpItemId()).queryFirst();
						detailItem.setFbaBoxUpInfoId(relevanceInfo.getFbaBoxInfoId());
						tccFbaBoxDetailMapper.update(detailItem);
					}
				}
			}
		}

		//修改计划单箱规编辑保存次数
		int boxRoleEditNo= tccFbaPlan.getBoxRoleEditNo()!=null?tccFbaPlan.getBoxRoleEditNo():0;

		tccFbaPlan.setBoxRoleEditNo(boxRoleEditNo+1);
		tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.NO.value);
		tccFbaPlanMapper.update(tccFbaPlan);

		return R.ok();
	}


	//验证 箱规编辑 保存的传参
	public R checkBoxRoleEditInfo(Map<String, Object> params) throws Exception{
		TccFbaBoxUpBoxRoleEdit tccFbaBoxUpBoxRoleEdit = new TccFbaBoxUpBoxRoleEdit();

		if(checkUtil.isNullByObject(params.get("bid"))){
			return R.error("单号为空！");
		}
		if(checkUtil.isNullByObject(params.get("boxUpUserId"))){
			return R.error("装箱人信息为空！");
		}
		String bid = params.get("bid").toString();
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
		int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
		//int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）

		//**** 验证：箱子数量
		int boxNum = 0;
		{
			if(checkUtil.isNullByObject(params.get("boxNum"))){
				return R.error("箱子数量信息为空！");
			}
			if(!checkUtil.isPositiveInteger(params.get("boxNum").toString())){
				return R.error("箱子数量应为正整数！");
			}
			boxNum = Integer.parseInt(params.get("boxNum").toString());

			if(tccFbaPlan.getEvenlyBoxNum() ==0 || creationMethod==0){// 均分箱数 = 0 ||下单方式 = 手动
				int boxNumMax = 0;
				//获取最大箱子数量
				TbStaticConfig tbStaticConfig = new TbStaticConfig().setKeyOne("TCC_FbaBoxUp").setKeyTwo("boxNumMax").queryFirst();
				if(tbStaticConfig!=null && tbStaticConfig.getName()!=null){
					boxNumMax = Integer.parseInt(tbStaticConfig.getName());
				}
				if(boxNum > boxNumMax){
					return R.error("箱子数量超过可设置的最大箱子数量（"+boxNumMax+"）！");
				}
			}

		}

		//**** 验证：表1数据
		List<Map<String,Object>> dataList = new ArrayList<>();
		{
			if(checkUtil.isNullByObject(params.get("dataList"))){
				return R.error("表1详情数据为空！");
			}
			dataList = ToolUtil.jsonArrayToList(JSON.parseArray(params.get("dataList").toString()));
			StringBuilder errorMsg = new StringBuilder();//错误信息 - 总

			List<Map<String,Object>> dataListByNum = dataList.stream().filter(e->e.get("numOrWeight").toString().equals("num")).collect(Collectors.toList());
			for (Map<String,Object> dataInfo:dataListByNum) {
				StringBuilder errorMsgByRow = new StringBuilder();//错误信息 - 每行
				String code = dataInfo.get("commodityCode").toString();//商品编码
				int boxUpNum = Integer.parseInt(dataInfo.get("boxUpNum").toString());//包装组数量
				int averageBoxUpNum = Integer.parseInt(dataInfo.get("averageBoxUpNum").toString());//均分装箱数量
				//遍历每个箱子信息
				int boxUpNumByInput = 0;//填写的数量
				for(int i=1;i<=boxNum;i++){
					Object boxNumByItem = dataInfo.get("box"+i);
					if(checkUtil.isNotNullByObject(boxNumByItem)){
						//验证所填参数格式
						if(!checkUtil.isZeroOrPositiveInt(boxNumByItem.toString().trim())){
							errorMsgByRow.append("箱子").append(i).append("所填写的数量格式有误（0或正整数）；");
						}
						//累加，用以后面判断
						if(checkUtil.isZeroOrPositiveInt(boxNumByItem.toString().trim())){//若格式正确
							boxUpNumByInput = boxUpNumByInput + Integer.parseInt(boxNumByItem.toString());
						}
						//若有均分箱数 ，验证：均分装箱数量=每箱数量 + -1 内
						if(tccFbaPlan.getEvenlyBoxNum() !=0 && creationMethod==1) {// 均分箱数 != 0 ||下单方式 = 自动
							if(checkUtil.isZeroOrPositiveInt(boxNumByItem.toString().trim())){//若格式正确
								int boxNumValue = Integer.parseInt(boxNumByItem.toString());
								int boxNumMin = averageBoxUpNum-1;
								int boxNumMax = averageBoxUpNum+1;
								if(boxNumValue<boxNumMin || boxNumValue>boxNumMax){
									errorMsgByRow.append("箱子")
											.append(i)
											.append("所填写的数量应在\"均分装箱数量±1\"[")
											.append(boxNumMin)
											.append(",")
											.append(boxNumMax)
											.append("]的范围内；")
									;
								}
							}
						}
					}
				}

				//包装数组数量 与 每箱SKU数量之和 差值不能超过 MAX（5、包装数组数量 * 5%）
				if(boxUpNum!=boxUpNumByInput){
					if(boxUpNumByInput>boxUpNum){
						errorMsgByRow.append("各箱子所填写的数量总计不能大于包装组数量；");
					}else {
						//手动不判断差额，自动需要判断
						if(creationMethod == 1){//自动
							int minCheckMum;
							if(new BigDecimal(boxUpNum*0.05).compareTo(new BigDecimal(5))>0){
								minCheckMum = new BigDecimal(boxUpNum*0.05).intValue();
							}else {
								minCheckMum = 5;
							}
							if(boxUpNum - boxUpNumByInput > minCheckMum){
								errorMsgByRow
										.append("各箱子所填写的数量总计与包装组数量差额不能超过")
										.append(minCheckMum)
										.append("；");
							}
						}
					}
				}
				if(errorMsgByRow.length()>0){
					errorMsg.append("表1商品编码").append(code).append("所填信息有误：").append(errorMsgByRow).append("</br>");
				}
			}
			//验证所有箱子是否都有大于0的数量
			StringBuilder errorMsgByRow = new StringBuilder();//错误信息 - 每行

			//手动不判断 0
			if(creationMethod == 1) {//自动
				for(int i=1;i<=boxNum;i++){
					int boxUpNumByInput = 0;//填写的数量
					for (Map<String,Object> dataInfo:dataList) {
						Object boxNumByItem = dataInfo.get("box"+i);
						if(checkUtil.isNotNullByObject(boxNumByItem)){
							if(checkUtil.isZeroOrPositiveInt(boxNumByItem.toString().trim())){
								boxUpNumByInput = boxUpNumByInput + Integer.parseInt(boxNumByItem.toString());
							}
						}
					}
					if(boxUpNumByInput<=0){
						errorMsgByRow.append("箱子").append(i).append("所填写的数量总计应大于0；");
					}
				}
			}

			if(errorMsgByRow.length()>0){
				errorMsg.append("表1所填信息有误：").append(errorMsgByRow).append("</br>");
			}

			if(errorMsg.length()>0){
				return R.error(errorMsg.toString());
			}
		}



		//**** 验证重量数据
		List<Map<String,Object>> dataListByWeight = dataList.stream().filter(e->e.get("numOrWeight").toString().equals("weight")).collect(Collectors.toList());
		{
			StringBuilder errorMsg = new StringBuilder();//错误信息 - 总
			for (Map<String,Object> dataInfo:dataListByWeight) {
				for(int i=1;i<=boxNum;i++){
					StringBuilder errorMsgByRow = new StringBuilder();//错误信息 - 每行
					if(checkUtil.isNullByObject(dataInfo.get("box"+i))){
						errorMsgByRow.append("箱子").append(i).append("的重量为空；");
					}else {
						if(!checkUtil.checkNumber(dataInfo.get("box"+i).toString().trim())){
							errorMsgByRow.append("箱子").append(i).append("的重量应为数字；");
						}else {
							if(new BigDecimal(dataInfo.get("box"+i).toString()).compareTo(new BigDecimal(30))>0) {
								errorMsgByRow.append("箱子").append(i).append("的重量应<30kg ；");
							}
						}
					}
					if(errorMsgByRow.length()>0){
						errorMsg.append(errorMsgByRow).append("</br>");
					}
				}
				if(errorMsg.length()>0){
					return R.error(errorMsg.toString());
				}
			}
		}


		//**** 验证：表2数据
		List<Map<String,Object>> dataListByBox = new ArrayList<>();
		{
			if(checkUtil.isNullByObject(params.get("dataListByBox"))){
				return R.error("表2详情数据为空！");
			}
			dataListByBox = ToolUtil.jsonArrayToList(JSON.parseArray(params.get("dataListByBox").toString()));
			StringBuilder errorMsg = new StringBuilder();//错误信息 - 总
			int row = 1;
			for (Map<String,Object> dataInfo:dataListByBox) {
				StringBuilder errorMsgByRow = new StringBuilder();//错误信息 - 每行
				if(checkUtil.isNullByObject(dataInfo.get("boxLong"))) errorMsgByRow.append("长为空；");
				if(checkUtil.isNullByObject(dataInfo.get("boxWide"))) errorMsgByRow.append("宽为空；");
				if(checkUtil.isNullByObject(dataInfo.get("boxHigh"))) errorMsgByRow.append("高为空；");
				//if(checkUtil.isNullByObject(dataInfo.get("boxWeight"))) errorMsgByRow.append("重量为空；");
				if(errorMsgByRow.length()>0){
					errorMsg.append("包装尺寸设置的第").append(row).append("行数据：").append(errorMsgByRow).append("</br>");
					row++;
					continue;
				}
				if(!checkUtil.checkNumber(dataInfo.get("boxLong").toString().trim())) errorMsgByRow.append("长应为数字；");
				if(!checkUtil.checkNumber(dataInfo.get("boxWide").toString().trim())) errorMsgByRow.append("宽应为数字；");
				if(!checkUtil.checkNumber(dataInfo.get("boxHigh").toString().trim())) errorMsgByRow.append("高应为数字；");
				//if(!checkUtil.checkNumber(dataInfo.get("boxWeight").toString().trim())) errorMsgByRow.append("重量应为数字；");
				if(errorMsgByRow.length()>0){
					errorMsg.append("包装尺寸设置的第").append(row).append("行数据：").append(errorMsgByRow).append("</br>");
					row++;
					continue;
				}
				//尺寸限制
				if(new BigDecimal(dataInfo.get("boxLong").toString()).compareTo(new BigDecimal(70))>0) errorMsgByRow.append("长应<70cm ；");
				if(new BigDecimal(dataInfo.get("boxWide").toString()).compareTo(new BigDecimal(60))>0) errorMsgByRow.append("宽应<60cm ；");
				if(new BigDecimal(dataInfo.get("boxHigh").toString()).compareTo(new BigDecimal(60))>0) errorMsgByRow.append("高应<60cm ；");
				//if(new BigDecimal(dataInfo.get("boxWeight").toString()).compareTo(new BigDecimal(30))>0) errorMsgByRow.append("重量应<30kg ；");
				if(errorMsgByRow.length()>0){
					errorMsg.append("包装尺寸设置的第").append(row).append("行数据：").append(errorMsgByRow).append("</br>");
				}
				row++;
			}
			//验证所有箱子是否都有勾选尺寸设置
			for(int i=1;i<=boxNum;i++){
				int isSet = 0;
				for (Map<String,Object> dataInfo:dataListByBox) {
					if(checkUtil.isNotNullByObject(dataInfo.get("box"+i)) && Integer.parseInt(dataInfo.get("box"+i).toString().trim()) == 1){
						isSet = 1;
					}
				}
				if(isSet == 0){
					errorMsg.append("箱子").append(i).append("未勾选尺寸设置；").append("</br>");
				}
			}

			if(errorMsg.length()>0){
				return R.error(errorMsg.toString());
			}
		}

		//返回数据
		tccFbaBoxUpBoxRoleEdit.setBid(params.get("bid").toString());//单号
		tccFbaBoxUpBoxRoleEdit.setUserId(params.get("boxUpUserId").toString());//装箱人工号
		tccFbaBoxUpBoxRoleEdit.setBoxNum(boxNum);//装箱数量
		tccFbaBoxUpBoxRoleEdit.setDataList(dataList);//表1数据
		tccFbaBoxUpBoxRoleEdit.setDataListByBox(dataListByBox);//表2数据
		return R.ok("验证通过",tccFbaBoxUpBoxRoleEdit);
	}

	/**
	 * FBA导入
	 * @param bid 装箱单号
	 * @param fbaNo FBA编号
	 * @param fbaTrackNo FBA追踪编号
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R fbaImport(String bid, String fbaNo,String fbaTrackNo) throws Exception{
		logger.info(ShiroUtils.getUserId()+"FBA导入:bid="+bid+"fbaNo="+fbaNo+"fbaTrackNo="+fbaTrackNo);

		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		if(tccFbaBoxUp!=null && tccFbaBoxUp.getId()!=null){
			//获取计划单信息
			TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
			int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
			if(creationMethod==0){//手动
				//先删除旧FBA信息、修改关联表信息
				storageMapper.deleteFbaBoxUpInfoByBid(bid);
				storageMapper.deleteFbaBoxRelevanceByBid(bid);

				TccFbaBoxUpInfo tccFbaBoxUpInfo = new TccFbaBoxUpInfo();
				tccFbaBoxUpInfo.setBoxUpBid(bid);
				tccFbaBoxUpInfo.setFbaNo(fbaNo);
				tccFbaBoxUpInfo.setFbaTrackNo(fbaTrackNo);
				tccFbaBoxUpInfo.setStatus(1);
				tccFbaBoxUpInfo.setSearchIsShow(1);//查询页是否展示0否1是
				tccFbaBoxUpInfo.setBidFbaPlan(tccFbaPlan.getBid());//计划单号
				tccFbaBoxUpInfoMapper.insert(tccFbaBoxUpInfo);

				//关联 商品装箱详情信息 与 FBA
				List<TccFbaBoxDetail> detailList = new TccFbaBoxDetail().setBidBoxUp(bid).queryList();
				if(detailList!=null && detailList.size()>0){
					for(TccFbaBoxDetail detailItem:detailList){
						detailItem.setFbaBoxUpInfoId(tccFbaBoxUpInfo.getId());
						tccFbaBoxDetailMapper.update(detailItem);
					}
				}


				//访问api
				R resByApi = fbaInboundApiService.getShipments(tccFbaBoxUp,fbaNo);
				if(resByApi.getCode().equals(R.Code.FAILED.value)){
					throw new RuntimeException(resByApi.getMsg());
				}

				return R.ok();

			}else {//自动
				return R.error("自动无需导入");
			}
		}else {
			return R.error("未查询到装箱单信息");
		}
		//return R.ok();
	}


	/**
	 * FBA导入（按箱）
	 * @param params 参数
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R fbaImportByBox(Map<String, Object> params) throws Exception{

		//保存列表信息
		List<Map<String, Object>> subDataList;

		String bid = params.get("bid").toString();
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		if(params.get("subData")!=null){
			//参数验证
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByGrid(subData);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}

		//先删除旧FBA信息、修改关联表信息
		storageMapper.deleteFbaBoxUpInfoByBid(bid);
		storageMapper.deleteFbaBoxRelevanceByBid(bid);

		List<TccFbaBoxUpInfo> infoList = new ArrayList<>();

		//根据FBA号去重
		Map<String, List<Map<String, Object>>> subDataListByGroup = subDataList.stream().collect(Collectors.groupingBy(e->e.get("fbaNo").toString()));
		subDataListByGroup.forEach((k, v) -> {
			TccFbaBoxUpInfo tccFbaBoxUpInfo = JSON.parseObject(JSON.toJSONString(v.get(0)), TccFbaBoxUpInfo.class);
			tccFbaBoxUpInfo.setBoxUpBid(bid);
			tccFbaBoxUpInfo.setStatus(1);
			tccFbaBoxUpInfo.setSearchIsShow(0);//查询页是否展示0否1是
			tccFbaBoxUpInfo.setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan());
			tccFbaBoxUpInfo.setFbaNo(v.get(0).get("fbaNo").toString());
			tccFbaBoxUpInfo.setFbaTrackNo(v.get(0).get("fbaTrackNo").toString());
			tccFbaBoxUpInfoMapper.insert(tccFbaBoxUpInfo);
			infoList.add(tccFbaBoxUpInfo);
			for(Map<String, Object> boxItem:v){
				TccFbaBox tccFbaBox = new TccFbaBox().setBidBoxUp(bid).setBoxNo(Integer.parseInt(boxItem.get("boxNo").toString())).queryFirst();
				//新增包装组关联表信息
				TccFbaBoxRelevance tccFbaBoxRelevance = new TccFbaBoxRelevance()
						.setBoxId(tccFbaBox.getId())//箱子表id（TCC_FbaBox）
						.setRelevanceType(3)//关联类型（1其他、2关联商品、3关联箱子、4关联装箱详情）
						.setFbaBoxInfoId(tccFbaBoxUpInfo.getId())
						.setRemark(bid)//备注
						.setStatus(1);
				tccFbaBoxRelevanceMapper.insert(tccFbaBoxRelevance);
			}
		});


		//关联 商品装箱详情信息 与 FBA
		List<TccFbaBoxDetail> detailList = new TccFbaBoxDetail().setBidBoxUp(bid).queryList();
		if(detailList!=null && detailList.size()>0){
			for(TccFbaBoxDetail detailItem:detailList){
				TccFbaBoxRelevance relevanceInfo = new TccFbaBoxRelevance().setBoxId(detailItem.getBoxId()).queryFirst();
				if(relevanceInfo!=null && relevanceInfo.getId()!=null){
					detailItem.setFbaBoxUpInfoId(relevanceInfo.getFbaBoxInfoId());
					tccFbaBoxDetailMapper.update(detailItem);
				}
			}
		}

		//访问api
		for(TccFbaBoxUpInfo item:infoList){
			//访问api
			R resByApi = fbaInboundApiService.getShipments(tccFbaBoxUp,item.getFbaNo());
			if(resByApi.getCode().equals(R.Code.FAILED.value)){
				throw new RuntimeException(resByApi.getMsg());
			}
		}

		return R.ok(EditDto.reloadPage("/web/storage/tccFbaBoxUp/toEdit?bid="+bid));

	}




	/**
	 * 修改FBA仓库
	 * @param params 参数
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R updateFbaWarehouse(Map<String, Object> params) throws Exception{

		//保存列表信息
		List<Map<String, Object>> subDataList;

		String bid = params.get("bid").toString();

		if(params.get("subData")!=null){
			//参数验证
			JSONArray subData = JSON.parseArray(params.get("subData").toString());
			CheckByGrid checkByGrid = checkParamsByUpdateFbaWarehouseGrid(subData);
			if(checkUtil.isNotNullByObject(checkByGrid.getErrMsg())){
				return R.error(checkByGrid.getErrMsg());
			}
			subDataList = checkByGrid.getSubDataList();
		}else {
			return R.error("列表信息为空！");
		}
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		//验证状态
//		List<TccFbaBoxUpEnum.BoxState> getEditInfo = TccFbaBoxUpEnum.BoxState.getEditInfo();
//		if(!TccFbaBoxUpEnum.BoxState.checkStatus(getEditInfo,tccFbaBoxUp.getBoxState())){
//			return R.error("只有："+TccFbaBoxUpEnum.BoxState.getNameStrByList(getEditInfo)+"才可修改！");
//		}


		for(Map<String, Object> item:subDataList){
			//修改仓库信息
			storageMapper.updateBoxUpFbaWarehouseByFbaNo(item.get("fbaNo").toString(),bid,item.get("fbaWarehouse").toString());
		}

		return R.ok(EditDto.reloadPage("/web/storage/tccFbaBoxUp/updateFbaWarehouse?bid="+bid));

	}




	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByGrid(JSONArray subDataArray) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		String backMsg = "";
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}

			//验证
			for(int i = 0;i<subDataList.size();i++){
				String backMsgByRow = "";
				Map<String, Object> subData = subDataList.get(i);

				if(checkUtil.isNullByObject(subData.get("fbaNo"))){//非空验证
					backMsgByRow += "FBA编号为空；";
				}
				if(checkUtil.isNullByObject(subData.get("fbaTrackNo"))){//非空验证
					backMsgByRow += "FBA追踪编码为空；";
				}
				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
				}
			}
		}else{
			backMsg = "列表信息为空";
		}
		checkByGrid.setErrMsg(backMsg);
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}




	/**
	 * 子表参数验证
	 */
	public CheckByGrid checkParamsByUpdateFbaWarehouseGrid(JSONArray subDataArray) throws Exception {
		CheckByGrid checkByGrid = new CheckByGrid();
		String backMsg = "";
		List<Map<String, Object>> subDataList = new ArrayList<>();

		if(subDataArray!=null && subDataArray.size()>0){
			for (int i = 0; i < subDataArray.size(); i++) {
				JSONObject jsonObject = subDataArray.getJSONObject(i);
				Map<String, Object> paramsNewByRecord = new HashMap<>();
				for (String key : jsonObject.keySet()) {
					paramsNewByRecord.put(key, jsonObject.get(key));
				}
				subDataList.add(paramsNewByRecord);
			}

			//验证
			for(int i = 0;i<subDataList.size();i++){
				String backMsgByRow = "";
				Map<String, Object> subData = subDataList.get(i);

				if(checkUtil.isNullByObject(subData.get("fbaNo"))){//非空验证
					backMsgByRow += "FBA编号为空；";
				}
				if(checkUtil.isNullByObject(subData.get("fbaWarehouse"))){//非空验证
					backMsgByRow += "FBA仓库为空；";
				}

				//验证：相同FBA编号，FBA仓库必须相同
				for(Map<String, Object> item:subDataList){
					if(checkUtil.isNullByObject(item.get("fbaNo")) && checkUtil.isNullByObject(item.get("fbaWarehouse"))){
						if(item.get("fbaNo").toString().equals(subData.get("fbaNo").toString())){
							if(!item.get("fbaWarehouse").toString().equals(subData.get("fbaWarehouse").toString())){
								backMsgByRow += "相同FBA【"+item.get("fbaNo").toString()+"】的仓库必须相同；";
							}
						}
					}

				}

				if(checkUtil.isNotNullByObject(backMsgByRow)){
					backMsg += "列表第" + (i+1) + "行，" + backMsgByRow;
				}
			}
		}else{
			backMsg = "列表信息为空";
		}
		checkByGrid.setErrMsg(backMsg);
		checkByGrid.setSubDataList(subDataList);

		return checkByGrid;
	}



	/**
	 * 计划取消
	 * @param bidFbaPlan 计划单号
	 */
//	@Override
//	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
//	public R planCancel(String bidFbaPlan) throws Exception{
//		logger.info(ShiroUtils.getUserId()+"计划取消:bidFbaPlan="+bidFbaPlan);
//		//验证状态
//		List<TccFbaBoxUp> fbaBoxUpList = new TccFbaBoxUp().setBidFbaPlan(bidFbaPlan).queryList();
//		if(fbaBoxUpList!=null && fbaBoxUpList.size()>0){
//
//			for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
//				//已取消
//				if(tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_CANCEL.value)){
//					return R.error("该计划单"+TccFbaBoxUpEnum.BoxState.YES_CANCEL.name+"；");
//				}
//				//已审核
//				if(tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_PASS.value)){
//					return R.error("该计划单"+TccFbaBoxUpEnum.BoxState.YES_PASS.name+"；");
//				}
//			}
//		}else {
//			return R.error("计划单号有误；");
//		}
//		//**** 1、API取消货件 ***
//		/*
//		R res = fbaInboundApiService.cancelInboundPlan(fbaBoxUpList.get(0),null);
//		if(!res.getCode().equals(R.Code.SUCCESS.value)) {
//			logger.error("FBA装箱单取消失败:"+res.getMsg());
//			return R.error(res.getMsg());
//		}
//		 */
//		List<TccFbaCancelItemByAdd> cancelItemList = new ArrayList<>();
//
//		//**** 2、组装单---货件状态变更 ***
//		for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
//			TccFbaCancelItemByAdd tccFbaCancelItemByAdd = new TccFbaCancelItemByAdd();
//			//填入取消单信息
//			Integer shipmentState = null;
//			if(tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_UP.value)){//已装箱
//				shipmentState = TccFbaCancelEnum.ShipmentState.YES_BOXUP.value;
//			}else {
//				//判断配货清单号是否为空
//				if(checkUtil.isNotNullByObject(tccFbaBoxUp.getDistributionBid())){
//					shipmentState = TccFbaCancelEnum.ShipmentState.NOT_BOXUP_YES_PREPARE.value;//未装箱/已配货
//				}else {
//					shipmentState = TccFbaCancelEnum.ShipmentState.NOT_BOXUP_NOT_PREPARE.value;//未装箱/未配货
//				}
//			}
//			logger.info(ShiroUtils.getUserId()+"计划取消:shipmentState="+TccFbaCancelEnum.ShipmentState.getName(shipmentState));
//			tccFbaCancelItemByAdd.setShipmentState(shipmentState);
//			tccFbaCancelItemByAdd.setBidFbaBoxUp(tccFbaBoxUp.getBid());
//			cancelItemList.add(tccFbaCancelItemByAdd);
//
//			tccFbaBoxUp.setBoxState(TccFbaBoxUpEnum.BoxState.YES_CANCEL.value);//已取消
//			tccFbaBoxUpMapper.update(tccFbaBoxUp);
//		}
//		//**** 3、FBA计划单状态变更 ***
//		logger.info(ShiroUtils.getUserId()+"FBA计划单状态变更");
//		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(bidFbaPlan).queryFirst();
//		tccFbaPlan.setStatus(TccFbaPlanEnum.Status.CANCELED.value);
//		tccFbaPlanMapper.update(tccFbaPlan);
//
//		//**** 4、生成FBA取消单 ***
//		R resByCancel = tccFbaCancelService.addCancel(bidFbaPlan,cancelItemList);
//		if (resByCancel.getCode() != 0){
//			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//			logger.info(ShiroUtils.getUserId()+"生成FBA取消单失败,失败原因:" + resByCancel.getMsg());
//			return R.error("计划取消失败,失败原因:" + resByCancel.getMsg());
//		}
//		return R.ok();
//	}





	/**
	 * 计划取消(运营)
	 * @param bidFbaPlan 计划单号
	 */
//	@Override
//	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
//	public R planCancelByOperation(String bidFbaPlan) throws Exception{
//		logger.info(ShiroUtils.getUserId()+"计划取消:bidFbaPlan="+bidFbaPlan);
//		//验证状态
//		//获取 装箱单子列表信息
//		List<TccFbaBoxUpItem> boxUpItemList = new TccFbaBoxUpItem()
//				.setBidFbaPlan(bidFbaPlan)
//				.queryList();
//
//		if(boxUpItemList!=null && boxUpItemList.size()>0) {
//			for (TccFbaBoxUpItem item : boxUpItemList) {
//				if(item.getTagStateGoods()==1){
//					return R.error("商品标签已打印，无法进行取消；");
//				}
//				if(item.getTagStateTransparent()==1){
//					return R.error("透明标签已打印，无法进行取消；");
//				}
//				if(item.getTagStateEur()==1){
//					return R.error("欧代标签已打印，无法进行取消；");
//				}
//				TccFbaBoxUp fbaBoxUp = new TccFbaBoxUp().setBid(item.getBidBoxUp()).queryFirst();
//				if(fbaBoxUp!=null && fbaBoxUp.getDistributionBid()!=null && !"".equals(fbaBoxUp.getDistributionBid())){
//					return R.error("配货清单已打印，无法进行取消；");
//				}
//			}
//		}
//
//		//生成取消单
//		R cancelRes= planCancel(bidFbaPlan);
//		if(cancelRes.getCode().equals(R.Code.FAILED.value)){//失败
//			return cancelRes;
//		}
//
//		//直接取消确认
//		Map<String, Object> tccFbaCancelMap = new TccFbaCancel().setBidFbaPlan(bidFbaPlan).queryFirstMap();
//		R cancelPassRes= tccFbaCancelService.passCancel(tccFbaCancelMap,null,false,true);
//		if(cancelPassRes.getCode().equals(R.Code.FAILED.value)){//失败
//			return R.error("生成取消单成功，但取消确认失败，请到取消单进行取消确认；");
//		}
//		return R.ok();
//	}


	/**
	 * 装箱审核 - 手动
	 * @param bidFbaPlan 计划单号
	 */
	@Override
	public R examineByHand(String bidFbaPlan) throws Exception{
		R checkRes = examineBeforeCheck(bidFbaPlan);
		if(checkRes.getCode().equals(R.Code.FAILED.value)){//验证未通过
			return checkRes;
		}
		return examine(bidFbaPlan,0);
	}


	/**
	 * 装箱审核前 - 验证
	 * @param bidFbaPlan 计划单号
	 */
	@Override
	@Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
	public R examineBeforeCheck(String bidFbaPlan) throws Exception{
		logger.info(ShiroUtils.getUserId()+"装箱审核:" + bidFbaPlan);
		List<TccFbaBoxUp> fbaBoxUpList = new TccFbaBoxUp().setBidFbaPlan(bidFbaPlan).queryList();
		//获取 装箱单FBA信息表
		List<TccFbaBoxUpInfo> boxUpInfoList = new TccFbaBoxUpInfo()
				.addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BoxUpBid")
				.where("B.BidFbaPlan = '"+bidFbaPlan+"'")
				.queryList();

		//获取计划单信息
		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(bidFbaPlan).queryFirst();

		int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
		int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）

		//验证
		if(fbaBoxUpList!=null && fbaBoxUpList.size()>0){
			for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
				//验证状态
				//已取消
				if(tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_CANCEL.value)){
					return R.error("装箱单："+tccFbaBoxUp.getBid()+TccFbaBoxUpEnum.BoxState.YES_CANCEL.name+"；");
				}
				//已审核
				if(tccFbaBoxUp.getBoxState().equals(TccFbaBoxUpEnum.BoxState.YES_PASS.value)){
					return R.error("装箱单："+tccFbaBoxUp.getBid()+TccFbaBoxUpEnum.BoxState.YES_PASS.name+"；");
				}

				//配货清单打印
//				if(checkUtil.isNullByObject(tccFbaBoxUp.getDistributionBid())){
//					return R.error("装箱单："+tccFbaBoxUp.getBid()+"配货清单未打印；");
//				}

				//验证箱规
				int countByBox = new TccFbaBox().setBidBoxUp(tccFbaBoxUp.getBid()).count();
				if(countByBox<=0){
					return R.error("装箱单："+tccFbaBoxUp.getBid()+"还未进行箱规编辑；");
				}

				List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = boxUpInfoList
						.stream()
						.filter(e->e.getBoxUpBid().equals(tccFbaBoxUp.getBid()))
						.collect(Collectors.toList());

				if(creationMethod == 0 || deliverState == 1){//手动 || 按SKU自动发货
					if(tccFbaBoxUpInfoList.size()>0){
						for(TccFbaBoxUpInfo fbaBoxUpInfo : tccFbaBoxUpInfoList){
							if(checkUtil.isNullByObject(fbaBoxUpInfo.getFbaNo())
									|| checkUtil.isNullByObject(fbaBoxUpInfo.getFbaWarehouseAddr())){
								return R.error("装箱单："+tccFbaBoxUp.getBid()+"FBA导入成功后才可以审核；");
							}
						}
					}else {
						return R.error("装箱单："+tccFbaBoxUp.getBid()+"FBA导入后才可以审核；");
					}
				}

			}
		}else {
			return R.error("计划单号有误；");
		}
		return R.ok();
	}


	/**
	 * 验证采购价 - 验证
	 * @param bidFbaPlan 计划单号
	 */
	@Override
	public R checkPurchaseAmount(String bidFbaPlan)throws Exception{
		List<TccFbaBoxUp> fbaBoxUpList = new TccFbaBoxUp().setBidFbaPlan(bidFbaPlan).queryList();
		//获取 装箱单子列表信息
		List<TccFbaBoxUpItem> boxUpItemList = new TccFbaBoxUpItem()
				.setBidFbaPlan(bidFbaPlan)
				.queryList();
		//获取箱规信息
		List<TccFbaBox> boxList = new TccFbaBox()
				.addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
				.where("B.BidFbaPlan = '"+bidFbaPlan+"'")
				.setOrderby("A.BoxNo")
				.queryList();
		List<TccFbaBoxDetail> boxDetailList = new TccFbaBoxDetail()
				.addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
				.where("B.BidFbaPlan = '"+bidFbaPlan+"'")
				.queryList();

		//获取物流方式维护表信息
		TccFbaLogisticsMethod tccFbaLogisticsMethod = new TccFbaLogisticsMethod().setSourceBid(bidFbaPlan).setSourceType(0).queryFirst();

		if(fbaBoxUpList!=null && fbaBoxUpList.size()>0 &&
				boxUpItemList!=null && boxUpItemList.size()>0 &&
				boxList!=null && boxList.size()>0 &&
				boxDetailList!=null && boxDetailList.size()>0 &&
				tccFbaLogisticsMethod!=null && tccFbaLogisticsMethod.getId()!=null
		){

			StringBuilder backMsg = new StringBuilder();//返回信息
			BigDecimal singleBoxReqAmountMin = tccFbaLogisticsMethod.getSingleBoxReqAmountMin();//单箱采购最低价
			BigDecimal singleBoxReqAmountMax = tccFbaLogisticsMethod.getSingleBoxReqAmountMax();//单箱采购最高价

			StringBuilder backMsgByBoxNo = new StringBuilder();//返回信息 - 箱号
			StringBuilder backMsgByAmount = new StringBuilder();//返回信息 - 金额

			for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
				String boxupBid = tccFbaBoxUp.getBid();//装箱单号

				List<TccFbaBox> fbaBoxListByBoxUpBid = boxList.stream().filter(e->e.getBidBoxUp().equals(boxupBid)).collect(Collectors.toList());
				for(TccFbaBox tccFbaBox : fbaBoxListByBoxUpBid){
					BigDecimal boxAmount = BigDecimal.ZERO;//单箱采购总价

					//计算、累加 单箱采购总价
					List<TccFbaBoxDetail> boxDetailListByBoxUpBid = boxDetailList.stream().filter(e->e.getBoxId().equals(tccFbaBox.getId())).collect(Collectors.toList());
					if(boxDetailListByBoxUpBid.size()>0){
						for(TccFbaBoxDetail tccFbaBoxDetail : boxDetailListByBoxUpBid){
							TccFbaBoxUpItem tccFbaBoxUpItem = boxUpItemList.stream().filter(e->e.getId().equals(tccFbaBoxDetail.getBoxUpItemId())).collect(Collectors.toList()).get(0);
							boxAmount = boxAmount.add(tccFbaBoxUpItem.getPurchaseAmount().multiply(new BigDecimal(tccFbaBoxDetail.getNum())));//采购价*数量 累加
						}
					}
					//判断是否在范围内
					if(boxAmount.compareTo(singleBoxReqAmountMin)<0 || boxAmount.compareTo(singleBoxReqAmountMax)>0){
						if(backMsgByBoxNo.length()<=0){
							backMsgByBoxNo.append(tccFbaBox.getBoxNo());
							backMsgByAmount.append(boxAmount);
						}else {
							backMsgByBoxNo.append("/").append(tccFbaBox.getBoxNo());
							backMsgByAmount.append("/").append(boxAmount);
						}
					}
				}

			}
			//拼接提示信息
			if(backMsgByBoxNo.length()>0){
				backMsg.append("箱号").append(backMsgByBoxNo).append("采购总价").append(backMsgByAmount)
						.append("，未在物流服务采购总价要求范围").append(singleBoxReqAmountMin).append("~").append(singleBoxReqAmountMax)
						.append("，是否继续发货，如继续发货系统会按照商品采购价格比例进行相应调整至物流服务采购总价要求范围内，请确认。");
				return R.error(backMsg.toString());
			}
		}
		return R.ok();
	}


	/**
	 * 装箱审核
	 * @param bidFbaPlan 计划单号
	 * @param isReCountPurchaseAmount 是否重新计算采购价  0否1是
	 */
	@Override
	@Transactional(propagation= Propagation.REQUIRES_NEW)
	public R examine(String bidFbaPlan,int isReCountPurchaseAmount) throws Exception{
		logger.info(ShiroUtils.getUserId()+"装箱审核:" + bidFbaPlan);
		List<TccFbaBoxUp> fbaBoxUpList = new TccFbaBoxUp().setBidFbaPlan(bidFbaPlan).queryList();

		//获取计划单信息
		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(bidFbaPlan).queryFirst();

		//获取计划单详情信息
		List<TccFbaPlanItem> tccFbaPlanItemList = new TccFbaPlanItem().setBidFbaPlan(bidFbaPlan).queryList();

		//获取 装箱单FBA信息表
		List<TccFbaBoxUpInfo> boxUpInfoList = new TccFbaBoxUpInfo()
				.addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BoxUpBid")
				.where("B.BidFbaPlan = '"+bidFbaPlan+"'")
				.queryList();

		//获取 装箱单子列表信息
		List<TccFbaBoxUpItem> boxUpItemList = new TccFbaBoxUpItem()
				.setBidFbaPlan(bidFbaPlan)
				.queryList();

		//获取箱规信息
		List<TccFbaBox> boxList = new TccFbaBox()
				.addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
				.where("B.BidFbaPlan = '"+bidFbaPlan+"'")
				.queryList();

		//获取装箱详情信息
		List<TccFbaBoxDetail> boxDetailList = new TccFbaBoxDetail()
				.addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
				.where("B.BidFbaPlan = '"+bidFbaPlan+"'")
				.queryList();

		logger.info(ShiroUtils.getUserId()+"装箱审核:boxList=" + boxList);
		logger.info(ShiroUtils.getUserId()+"装箱审核:boxDetailList=" + boxDetailList);

		//********************************** 1、调整采购价 **********************************
		{
			if(isReCountPurchaseAmount==1){//如果需要调整采购价

				//获取物流方式维护表信息
				TccFbaLogisticsMethod tccFbaLogisticsMethod = new TccFbaLogisticsMethod().setSourceBid(bidFbaPlan).setSourceType(0).queryFirst();
				BigDecimal singleBoxReqAmountMin = tccFbaLogisticsMethod.getSingleBoxReqAmountMin();//单箱采购最低价
				BigDecimal singleBoxReqAmountMax = tccFbaLogisticsMethod.getSingleBoxReqAmountMax();//单箱采购最高价

				for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
					String boxupBid = tccFbaBoxUp.getBid();//装箱单号

					List<TccFbaBox> fbaBoxListByBoxUpBid = boxList.stream().filter(e->e.getBidBoxUp().equals(boxupBid)).collect(Collectors.toList());
					for(TccFbaBox tccFbaBox : fbaBoxListByBoxUpBid){
						BigDecimal boxAmount = BigDecimal.ZERO;//单箱采购总价

						//计算 单箱采购总价
						List<TccFbaBoxDetail> boxDetailListByBoxUpBid = boxDetailList.stream().filter(e->e.getBoxId().equals(tccFbaBox.getId())).collect(Collectors.toList());
						if(boxDetailListByBoxUpBid.size()>0){
							for(TccFbaBoxDetail tccFbaBoxDetail : boxDetailListByBoxUpBid){
								TccFbaBoxUpItem tccFbaBoxUpItem = boxUpItemList.stream().filter(e->e.getId().equals(tccFbaBoxDetail.getBoxUpItemId())).collect(Collectors.toList()).get(0);
								boxAmount = boxAmount.add(tccFbaBoxUpItem.getPurchaseAmount().multiply(new BigDecimal(tccFbaBoxDetail.getNum())));//采购价*数量 累加
							}
						}

						if(boxAmount.compareTo(singleBoxReqAmountMin)<0){
							//单箱采购总价＜单箱采购最低价(￥)
							//该箱各商品采购单价=变成=（单箱采购最低价(￥)+10）*（商品采购单价*数量/商品采购总价）/数量  仅保留2位小数（实际值）

							if(boxDetailListByBoxUpBid.size()>0){
								for(TccFbaBoxDetail tccFbaBoxDetail : boxDetailListByBoxUpBid){
									TccFbaBoxUpItem tccFbaBoxUpItem = boxUpItemList.stream().filter(e->e.getId().equals(tccFbaBoxDetail.getBoxUpItemId())).collect(Collectors.toList()).get(0);
									BigDecimal purchaseAmount = (singleBoxReqAmountMin.add(new BigDecimal(10))) // 单箱采购最低价(￥)+10
											.multiply(
													(tccFbaBoxUpItem.getPurchaseAmount().multiply(new BigDecimal(tccFbaBoxDetail.getNum())))//商品采购单价*数量
															.divide(boxAmount, 10, RoundingMode.HALF_UP)///商品采购总价
											).divide(boxAmount, 2, RoundingMode.HALF_UP);///数量
									tccFbaBoxDetail.setPurchaseAmount(purchaseAmount);
									tccFbaBoxDetailMapper.update(tccFbaBoxDetail);
								}
							}

						}else {
							//单箱采购总价＞单箱采购最高价(￥)
							//该箱各商品采购单价=变成=（单箱采购最高价(￥)-10）*（商品采购单价*数量/商品采购总价）/数量  仅保留2位小数（实际值）

							if(boxDetailListByBoxUpBid.size()>0){
								for(TccFbaBoxDetail tccFbaBoxDetail : boxDetailListByBoxUpBid){
									TccFbaBoxUpItem tccFbaBoxUpItem = boxUpItemList.stream().filter(e->e.getId().equals(tccFbaBoxDetail.getBoxUpItemId())).collect(Collectors.toList()).get(0);
									BigDecimal purchaseAmount = (singleBoxReqAmountMax.subtract(new BigDecimal(10))) // 单箱采购最高价(￥)-10
											.multiply(
													(tccFbaBoxUpItem.getPurchaseAmount().multiply(new BigDecimal(tccFbaBoxDetail.getNum())))//商品采购单价*数量
															.divide(boxAmount, 10, RoundingMode.HALF_UP)///商品采购总价
											).divide(boxAmount, 2, RoundingMode.HALF_UP);///数量
									tccFbaBoxDetail.setPurchaseAmount(purchaseAmount);
									tccFbaBoxDetailMapper.update(tccFbaBoxDetail);
								}
							}
						}
					}
				}
			}else {
				for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
					List<TccFbaBoxDetail> boxDetailListByBoxUpBid = boxDetailList.stream().filter(e->e.getBidBoxUp().equals(tccFbaBoxUp.getBid())).collect(Collectors.toList());
					if(boxDetailListByBoxUpBid.size()>0){
						for(TccFbaBoxDetail tccFbaBoxDetail : boxDetailListByBoxUpBid){
							TccFbaBoxUpItem tccFbaBoxUpItem = boxUpItemList.stream().filter(e->e.getId().equals(tccFbaBoxDetail.getBoxUpItemId())).collect(Collectors.toList()).get(0);
							tccFbaBoxDetail.setPurchaseAmount(tccFbaBoxUpItem.getPurchaseAmount());
							tccFbaBoxDetailMapper.update(tccFbaBoxDetail);
						}
					}
				}
			}
		}


		//********************************** 2、生成发货单 **********************************
		{
			//获取 物流方式维护表 信息
			TccLogisticsMethod tccLogisticsMethod = new TccLogisticsMethod()
					.addLeftJoin("TCC_FbaLogisticsMethod B ON B.LogsticsWayId = A.Id")
					.where("B.SourceBid = '"+tccFbaPlan.getBid()+"'")
					.queryFirst();

			int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
			int deliverState = tccFbaPlan.getDeliverState();//发货计划（1按SKU自动发货，0按箱自动发货）

			//***** 拆分，按：目的地  *****
			Map<String, List<TccFbaBoxUpInfo>> groupsByStr = boxUpInfoList.stream().collect(Collectors.groupingBy(e->e.getFbaWarehouse()));

			logger.info("************ 装箱审核:计划单号=" + bidFbaPlan+"开始生成发货单 ************");
			//遍历，生成发货单
			groupsByStr.forEach((fbaWarehouse, fbaBoxUpInfoList) ->{

				logger.info("（1） 计划单号=" + bidFbaPlan+"目的地仓库="+fbaWarehouse);
				TccFbaDeliverAdd tccFbaDeliverAdd = new TccFbaDeliverAdd();
				tccFbaDeliverAdd.setTccLogisticsMethod(tccLogisticsMethod);//物流服务
				tccFbaDeliverAdd.setTccFbaPlan(tccFbaPlan);//fba计划单
				tccFbaDeliverAdd.setFbaWarehouse(fbaWarehouse);//目的地仓库
				tccFbaDeliverAdd.setFbaWarehouseAddr(fbaBoxUpInfoList.get(0).getFbaWarehouseAddr());//目的地仓库邮编

				List<TccFbaPlanItem> tccFbaPlanItemListByAdd = new ArrayList<>();//计划单详情
				List<TccFbaDeliverItemAdd> tccFbaDeliverItemAddList = new ArrayList<>();//FBA信息

				//遍历fba信息
				fbaBoxUpInfoList.forEach(fbaInfo->{
					logger.info("（2） 计划单号=" + bidFbaPlan+"，FbaNo="+fbaInfo.getFbaNo());
					//获取 fba 对应的 装箱详情 信息
					List<TccFbaBoxDetail> boxDetailListByFbaId = boxDetailList.stream().filter(e->e.getFbaBoxUpInfoId().equals(fbaInfo.getId())).collect(Collectors.toList());
					if(boxDetailListByFbaId.size()>0){
						//获取 装箱详情 对应的 装箱单商品详情 信息
						List<TccFbaBoxUpItem> boxUpItemListByDetail = boxUpItemList.stream().filter(e->{
							List<TccFbaBoxDetail> boxDetailLisByFbaId_ByItemId = boxDetailListByFbaId.stream()
									.filter(detailItem->detailItem.getBoxUpItemId().equals(e.getId()))
									.collect(Collectors.toList());
							return boxDetailLisByFbaId_ByItemId.size()>0;
						}).collect(Collectors.toList());
						//获取 装箱单商品详情 对应的 计划单子列表 信息
						List<TccFbaPlanItem> tccFbaPlanItemListByBoxUpItem = tccFbaPlanItemList.stream().filter(e->{
							List<TccFbaBoxUpItem> boxUpItemListByDetail_ByPlanItemId = boxUpItemListByDetail.stream()
									.filter(item->item.getFbaPlanItemId().equals(e.getId()))
									.collect(Collectors.toList());
							return boxUpItemListByDetail_ByPlanItemId.size()>0;
						}).collect(Collectors.toList());

						//填入计划单子列表
						if(tccFbaPlanItemListByBoxUpItem.size()>0){
							tccFbaPlanItemListByAdd.addAll(tccFbaPlanItemListByBoxUpItem);
						}

						//FBA箱子信息
						TccFbaDeliverItemAdd tccFbaDeliverItemAdd = new TccFbaDeliverItemAdd();
						tccFbaDeliverItemAdd.setFbaBoxUpInfoId(fbaInfo.getId());//装箱单FBA信息id（TCC_FbaBoxUpInfo）
						tccFbaDeliverItemAdd.setDeliveryWindowOptionId(fbaInfo.getDeliveryWindowOptionId());//配送窗口选项ID
						tccFbaDeliverItemAdd.setTransportationOptionId(fbaInfo.getTransportationOptionId());//运输选项ID
						tccFbaDeliverItemAdd.setFbaBoxUpBid(fbaInfo.getBoxUpBid());//FBA装箱单号

						//获取 装箱详情 对应的 FBA箱子 信息
						List<TccFbaBox> boxListByDetail = boxList.stream().filter(e->{
							List<TccFbaBoxDetail> boxUpItemListByDetail_ByBoxId = boxDetailListByFbaId.stream()
									.filter(item->item.getBoxId().equals(e.getId()))
									.collect(Collectors.toList());
							return boxUpItemListByDetail_ByBoxId.size()>0;
						}).collect(Collectors.toList());

						//FBA箱子信息
						List<TccFbaDeliverSonAdd> tccFbaDeliverSonAddList = new ArrayList<>();
						for(TccFbaBox tccFbaBox : boxListByDetail){
							String boxNo = "";
							if(creationMethod==0){//下单方式(0.手动|1.自动)
								boxNo = fbaInfo.getFbaNo() + "U"+String.format("%0"+6+"d", tccFbaBox.getBoxNo());
								storageMapper.updateFbaBoxDetailBoxNo(tccFbaBox.getId(),boxNo);
							}else {
								List<TccFbaBoxDetail> boxDetailListByFbaIdAndBoxId = boxDetailListByFbaId.stream()
										.filter(e->e.getBoxId().equals(tccFbaBox.getId())).collect(Collectors.toList());
								if(boxDetailListByFbaIdAndBoxId.size()>0){
									boxNo = boxDetailListByFbaIdAndBoxId.get(0).getBoxNo();
								}
							}
							TccFbaDeliverSonAdd tccFbaDeliverSonAdd = new TccFbaDeliverSonAdd();
							tccFbaDeliverSonAdd.setBoxNo(boxNo);
							tccFbaDeliverSonAdd.setTccFbaBox(tccFbaBox);
							tccFbaDeliverSonAddList.add(tccFbaDeliverSonAdd);
							//tccFbaBox.setBoxCode(boxNo);
							tccFbaBoxMapper.update(tccFbaBox);
							logger.info("（3） 计划单号=" + bidFbaPlan+"，FbaNo="+fbaInfo.getFbaNo()+",boxNo = "+boxNo);
						}
						tccFbaDeliverItemAdd.setTccFbaDeliverSonAddList(tccFbaDeliverSonAddList);//FBA箱子信息
						logger.info("（2） 计划单号=" + bidFbaPlan+"，FbaNo="+fbaInfo.getFbaNo()+",FBA箱子信息 = "+tccFbaDeliverItemAdd);
						tccFbaDeliverItemAddList.add(tccFbaDeliverItemAdd);

					}
				});

				tccFbaDeliverAdd.setTccFbaPlanItemList(tccFbaPlanItemListByAdd);//计划单详情
				tccFbaDeliverAdd.setTccFbaDeliverItemAddList(tccFbaDeliverItemAddList);//FBA箱子信息
				//新增发货单
				try {
					tccFbaDeliverService.addFbaDeliver(tccFbaDeliverAdd);
				} catch (Exception e) {
					//TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
					e.printStackTrace();
					throw new RuntimeException(e.getMessage());
				}
//				try {
//					tccFbaDeliverService.addFbaDeliver(tccFbaDeliverAdd);
//				} catch (Exception e) {
//					TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//					e.printStackTrace();
//					throw new RuntimeException(e.getMessage());
//				}

			});
			logger.info("************ 装箱审核:计划单号=" + bidFbaPlan+"结束生成发货单 ************");
		}

		//修改计划单子表 实际数量
		for(TccFbaPlanItem tccFbaPlanItem:tccFbaPlanItemList) {
			int numRealityBox = tccFbaPlanItem.getNumRealityBox();
			List<TccFbaBoxUpItem> boxUpItemListByPlanItem = boxUpItemList.stream().filter(e->e.getFbaPlanItemId().equals(tccFbaPlanItem.getId())).collect(Collectors.toList());

			for(TccFbaBoxUpItem tccFbaBoxUpItem:boxUpItemListByPlanItem){
				List<TccFbaBoxDetail> boxDetailListByBoxUpItem = boxDetailList.stream().filter(e->e.getBoxUpItemId().equals(tccFbaBoxUpItem.getId())).collect(Collectors.toList());
				for(TccFbaBoxDetail tccFbaBoxDetail:boxDetailListByBoxUpItem){
					numRealityBox = numRealityBox+tccFbaBoxDetail.getNum();
				}
			}
			tccFbaPlanItem.setNumRealityBox(numRealityBox);
			tccFbaPlanItemMapper.update(tccFbaPlanItem);
		}

		//本单---货件状态变更
		for(TccFbaBoxUp tccFbaBoxUp : fbaBoxUpList){
			tccFbaBoxUp.setBoxState(TccFbaBoxUpEnum.BoxState.YES_PASS.value);//已审核
			//获取审核人信息
			TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
			if(tsUserChange!=null){
				tccFbaBoxUp.setExamineChangeId(tsUserChange.getId());// 审核人变更信息
			}
			tccFbaBoxUp.setExamineTime(new Date());//审核时间
			tccFbaBoxUpMapper.update(tccFbaBoxUp);
		}
		return R.ok();
	}





	/**
	 * 上传箱规信息
	 * @param bid 装箱单号
	 */
	@Override
	public R uploadPackingInfo(String bid) throws Exception{
		logger.info(ShiroUtils.getUserId()+"上传箱规信息:bid=" + bid);
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();

		List<TccFbaBoxUp> tccFbaBoxUpList = new TccFbaBoxUp().setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan()).queryList();
		for(TccFbaBoxUp item:tccFbaBoxUpList){
			int boxCount = new TccFbaBoxDetail().setBidBoxUp(item.getBid()).count();
			if(boxCount<=0){
				return R.error("装箱单:"+item.getBid()+"未进行箱规编辑！");
			}
		}
		R res = fbaInboundApiService.setPackingInformation(tccFbaBoxUp);
		logger.info(ShiroUtils.getUserId()+"上传箱规信息:bid=" + bid+"，结果："+res);
		return res;
	}


	/**
	 * 修改物流服务id（TCC_LogisticsMethod）
	 * @param bid 装箱单号
	 * @param logisticsMethodId 物流服务id（TCC_LogisticsMethod）

	@Override
	public R editLogisticsMethodId(String bid,long logisticsMethodId) throws Exception{
		logger.info(ShiroUtils.getUserId()+"修改物流服务id:bid=" + bid+"，logisticsMethodId="+logisticsMethodId);
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		TccLogisticsMethod tccLogisticsMethod = new TccLogisticsMethod().setId(logisticsMethodId).queryFirst();
		tccFbaBoxUp.setLogisticsMethodId(logisticsMethodId);
		tccFbaBoxUp.setLogisticsMethodName(tccLogisticsMethod.getLogsticsWay());
		tccFbaBoxUpMapper.update(tccFbaBoxUp);
		return R.ok();
	}
	 */


	/**
	 * 获取打印标签页的列表信息
	 *  bid //单号
	 * 	printType //打印类型：0商品标、1透明标、2欧代标
	 */
	@Override
	public R printTypeSearchList(String bid,int printType) throws Exception{
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		//存放返回数据
		List<TccFbaBoxUpPrintTag> resList = new ArrayList<>();

		if(tccFbaBoxUp!=null && tccFbaBoxUp.getBidFbaPlan()!=null){
			TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
			List<TccFbaPlanItem> fbaPlanItemList = new TccFbaPlanItem().setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan()).setOrderby("A.sku").queryList();
			List<TccFbaBoxUpItem> fbaBoxUpItemList = new TccFbaBoxUpItem().setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan()).queryList();
			if(fbaPlanItemList!=null && fbaPlanItemList.size()>0){
				for(TccFbaPlanItem item:fbaPlanItemList){
					TccFbaBoxUpPrintTag tccFbaBoxUpPrintTag = new TccFbaBoxUpPrintTag();
					tccFbaBoxUpPrintTag.setPlanItemId(item.getId());//计划单子列表id
					tccFbaBoxUpPrintTag.setCommodityCode(item.getCommodityCode());//商品编码
					tccFbaBoxUpPrintTag.setCommodityName(item.getCommodityName());//商品名称
					tccFbaBoxUpPrintTag.setAsin(item.getAsin());//asin
					tccFbaBoxUpPrintTag.setSku(item.getSku());//sku
					tccFbaBoxUpPrintTag.setFnSku(item.getFnSku());//fnSku
					tccFbaBoxUpPrintTag.setNumPlanDeliver(item.getNumPlanDeliver());//计划发货数量
					tccFbaBoxUpPrintTag.setSignCode(item.getSignCode());//透明标记编码
					tccFbaBoxUpPrintTag.setAnnexFile(item.getAnnexFile());//透明标记附件
					int isPrintGoods = 1;//商品标是否可打印 0否1是
					int isPrintTransparent = 1;//透明标是否可打印 0否1是
					int isPrintEur = 1;//欧代标是否可打印 0否1是

					TccFbaBoxUpItem tccFbaBoxUpItem = fbaBoxUpItemList.stream().filter(e->e.getFbaPlanItemId().equals(item.getId())).collect(Collectors.toList()).get(0);

					String statusPrintGoods = tccFbaBoxUpItem.getTagStateGoods()!=null && tccFbaBoxUpItem.getTagStateGoods().equals(TccFbaBoxUpItemEnum.TagStateGoods.YES.value)?"已打印":"";//商品标打印状态
					String statusPrintTransparent = tccFbaBoxUpItem.getTagStateTransparent()!=null && tccFbaBoxUpItem.getTagStateTransparent().equals(TccFbaBoxUpItemEnum.TagStateTransparent.YES.value)?"已打印":"";//透明标打印状态
					String statusPrintEur = tccFbaBoxUpItem.getTagStateEur()!=null && tccFbaBoxUpItem.getTagStateEur().equals(TccFbaBoxUpItemEnum.TagStateEur.YES.value)?"已打印":"";//欧代标打印状态
//
//					if(printType == 0){//0商品标
//						if(item.getNumPlanDeliver()<=0){//计划发货数量<=0
//							isPrintGoods = 0;
//							statusPrintGoods = "";
//						}
//					}else if(printType == 1){//1透明标
//						if(item.getIsSign().equals("否") || checkUtil.isNullByObject(item.getAnnexFile())){//透明标记(是/否 = 否
//							isPrintTransparent = 0;
//							statusPrintTransparent = "";
//						}
//					}else if(printType == 2){//2欧代标
//						TpAmazonShop tpAmazonShop = new TpAmazonShop().setId(tccFbaPlan.getShopId()).queryFirst();
//						if(tpAmazonShop!=null && tpAmazonShop.getEuStatus()!=null && tpAmazonShop.getEuStatus()==0){
//							isPrintEur = 0;
//							statusPrintEur = "";
//						}
//					}else {//未知类型
//						isPrintGoods = 0;
//						statusPrintGoods = "";
//						isPrintTransparent = 0;
//						statusPrintTransparent = "";
//						isPrintEur = 0;
//						statusPrintEur = "";
//					}
					if(item.getNumPlanDeliver()<=0){//计划发货数量<=0
						isPrintGoods = 0;
						statusPrintGoods = "";
					}
					if(item.getIsSign().equals("否") || checkUtil.isNullByObject(item.getAnnexFile())){//透明标记(是/否 = 否
						isPrintTransparent = 0;
						statusPrintTransparent = "";
					}
					TpAmazonShop tpAmazonShop = new TpAmazonShop().setId(tccFbaPlan.getShopId()).queryFirst();
					if(tpAmazonShop!=null && tpAmazonShop.getEuStatus()!=null && tpAmazonShop.getEuStatus()==0){
						isPrintEur = 0;
						statusPrintEur = "";
					}

					String statusPrint = "";
					if(!"".equals(statusPrintGoods)){
						statusPrint = "商品标";
					}
					if(!"".equals(statusPrintTransparent)){
						if(!"".equals(statusPrint)) statusPrint += "/";
						statusPrint += "透明标";
					}
					if(!"".equals(statusPrintGoods)){
						if(!"".equals(statusPrint)) statusPrint += "/";
						statusPrint += "欧代标";
					}
					if(!"".equals(statusPrint)) statusPrint += "已打印";
					tccFbaBoxUpPrintTag.setIsPrintGoods(isPrintGoods);
					tccFbaBoxUpPrintTag.setIsPrintTransparent(isPrintTransparent);
					tccFbaBoxUpPrintTag.setIsPrintEur(isPrintEur);
					tccFbaBoxUpPrintTag.setStatusPrintGoods(statusPrintGoods);
					tccFbaBoxUpPrintTag.setStatusPrintTransparent(statusPrintTransparent);
					tccFbaBoxUpPrintTag.setStatusPrintEur(statusPrintEur);
					tccFbaBoxUpPrintTag.setStatusPrint(statusPrint);
					resList.add(tccFbaBoxUpPrintTag);
				}
			}
		}
		return R.ok("成功",resList);
	}

	/**
	 * 打印欧代标打印
	 * @param params
	 * @return
	 * @throws Exception
	 */
	@Override
	public R europeanStandardPrint(Map<String, Object> params) throws Exception {
		List<PdfUtil.EuropeanStandardPrintDto> europeanStandardPrintDtoList = new ArrayList<>();

		Map<String, Object> tccFbaBoxUpMap = new TccFbaBoxUp()
				.setBid(params.get("bid").toString())
				.addLeftJoin("TCC_FbaPlan B ON B.bid = A.bidFbaPlan")
				.addLeftJoin("TP_AmazonShop C ON C.id = B.shopId")
				.addField("C.id shopId,C.EuAgent euAgent,C.EuAgentAddress euAgentAddress,C.manufacturer manufacturer,C.ManufacturerAddress manufacturerAddress")
				.queryFirstMap();

		String sql = "";
		if (params.get("planItemId") != null){
			sql = "A.id = " + params.get("planItemId");
		}else {
			sql = "A.bidFbaPlan = '" + tccFbaBoxUpMap.get("bidFbaPlan").toString() + "'";
		}

		LocalDate currentDate = LocalDate.now();
		LocalDate previousDate = currentDate.minusDays(7);
		// 创建SimpleDateFormat对象，设置英文日期格式
		SimpleDateFormat sdf = new SimpleDateFormat("EEEE, MMMM dd, yyyy", Locale.ENGLISH);
		Date date1 = Date.from(previousDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
		// 将日期转换为英文字符串
		String dateInEnglish = sdf.format(date1);

		List<Map<String, Object>> tccFbaPlanItemMapList = new TccFbaPlanItem()
				.addLeftJoin("TP_ProductActive B ON B.code = A.commodityCode")
				.addField("B.ageRange")
				.addLeftJoin("TP_AmazonShopProduct C ON C.fnSku = A.fnSku AND C.shopId = " + tccFbaBoxUpMap.get("shopId"))
				.addLeftJoin("TB_BaseinfoSppm D ON D.id = B.NameId")
				.addField("C.id amazonShopProductId")
				.addField("D.NameEn nameEn")
				.where(sql)
				.setOrderby("A.sku")
				.queryMap();
		for (Map<String, Object> tccFbaPlanItemMap : tccFbaPlanItemMapList){
			List<TbFileInfo> tbFileInfoList = new TbFileInfo().setSourceId(Long.valueOf(tccFbaPlanItemMap.get("amazonShopProductId").toString()))
					.setSourceType(43).setSourceCode("esAnnexFile").setStatus(1).queryList();

			String ageRange = "";
			if (tccFbaPlanItemMap.get("ageRange") != null && !tccFbaPlanItemMap.get("ageRange").equals("")){
				ageRange = tccFbaPlanItemMap.get("ageRange").toString();
			}

			String nameEn = "";
			if (tccFbaPlanItemMap.get("nameEn") != null && !tccFbaPlanItemMap.get("nameEn").equals("")){
				nameEn = tccFbaPlanItemMap.get("nameEn").toString();
			}
			PdfUtil.EuropeanStandardPrintDto dto = new PdfUtil.EuropeanStandardPrintDto(nameEn,
					tccFbaPlanItemMap.get("commodityCode").toString()+"/"+tccFbaPlanItemMap.get("fnSku").toString(),
					tccFbaBoxUpMap.get("euAgent").toString(), tccFbaBoxUpMap.get("euAgentAddress").toString(),
					tccFbaBoxUpMap.get("manufacturer").toString(),tccFbaBoxUpMap.get("manufacturerAddress").toString()
					,ageRange,dateInEnglish,Integer.valueOf(tccFbaPlanItemMap.get("numPlanDeliver").toString()),tbFileInfoList);
			europeanStandardPrintDtoList.add(dto);
		}


		String pdfFileName = "/" + params.get("bid").toString() + "OD" + ".pdf";
		String resUrl = PdfUtil.europeanStandardPrint(pdfFileName, europeanStandardPrintDtoList);
		return R.ok(resUrl);
	}

	/**
	 * 打印商品标
	 */
	@Override
	public R getGoodsPrintInfo(Map<String, Object> params) throws Exception {
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(params.get("bid").toString()).queryFirst();

		String sql = "";
		if (params.get("planItemId") != null){
			sql = "A.id = " + params.get("planItemId");
		}else {
			sql = "A.bidFbaPlan = '" + tccFbaBoxUp.getBidFbaPlan() + "'";
		}

		List<PdfUtil.GoodsDto> rows = new ArrayList<PdfUtil.GoodsDto>();
		List<Map<String, Object>> tccFbaPlanItemMapList = new TccFbaPlanItem()
				.addLeftJoin("TP_ProductActive B ON B.code = A.commodityCode")
				.addField("B.ageRange")
				.addLeftJoin("TB_BaseinfoSppm D ON D.id = B.NameId")
				.addField("D.NameEn nameEn")
				.where(sql)
				.setOrderby("A.sku")
				.queryMap();
		for (Map<String, Object> tccFbaPlanItemMap : tccFbaPlanItemMapList){
			String nameEn = "";
			if (tccFbaPlanItemMap.get("nameEn") != null){
				nameEn = tccFbaPlanItemMap.get("nameEn").toString();
			}
			rows.add(new PdfUtil.GoodsDto(nameEn,
					tccFbaPlanItemMap.get("commodityName").toString(),
					tccFbaPlanItemMap.get("fnSku").toString(),
					Integer.valueOf(tccFbaPlanItemMap.get("numPlanDeliver").toString())
					));
		}
		return R.ok(rows);
	}




	/**
	 * 修改对应标签状态
	 * 	bid //单号
	 * 	printType //打印类型：0商品标、1透明标、2欧代标
	 * 	oneOrAll //单条（0） or 全部 （1）
	 * 	planItemId //计划单子表id
	 */

	@Override
	public R updateTagState(Map<String, Object> params) throws Exception{
		String bid = params.get("bid").toString();//装箱单号
		int printType = Integer.parseInt(params.get("printType").toString());//打印类型：0商品标、1透明标、2欧代标
		int oneOrAll = Integer.parseInt(params.get("oneOrAll").toString());//单条（0） or 全部 （1）
		long planItemId;//计划单子表id

		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();


		List<TccFbaBoxUpItem> updateInfoList = new ArrayList<>();
		if(oneOrAll == 0){//单条（0）
			if(checkUtil.isNullByObject(params.get("planItemId"))){
				return R.error("单条列表信息为空");
			}
			planItemId = Long.parseLong(params.get("planItemId").toString());
			TccFbaBoxUpItem itemInfo = new TccFbaBoxUpItem().setBidBoxUp(bid).setFbaPlanItemId(planItemId).queryFirst();
			updateInfoList.add(itemInfo);
		}else {//全部 （1）
			updateInfoList = new TccFbaBoxUpItem().setBidBoxUp(bid).queryList();
		}

		//修改状态
		for(TccFbaBoxUpItem itemInfo : updateInfoList){
			//打印类型：0商品标、1透明标、2欧代标
			if(printType==0){
				itemInfo.setTagStateGoods(TccFbaBoxUpItemEnum.TagStateGoods.YES.value);
			}else if(printType==1){
				itemInfo.setTagStateTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.YES.value);
			}else if(printType==2){
				itemInfo.setTagStateEur(TccFbaBoxUpItemEnum.TagStateEur.YES.value);
			}
			//修改
			tccFbaBoxUpItemMapper.update(itemInfo);
		}

		//修改主表标签打印状态
        List<TccFbaBoxUpItem> itemList = new TccFbaBoxUpItem().setBidBoxUp(bid).queryList();
		long tagStateGoodsYes = itemList.stream().filter(e->e.getTagStateGoods().equals(TccFbaBoxUpItemEnum.TagStateGoods.YES.value)).count();
        long tagStateTransparentYes = itemList.stream().filter(e->e.getTagStateTransparent().equals(TccFbaBoxUpItemEnum.TagStateTransparent.YES.value)).count();
        long tagStateEurYes = itemList.stream().filter(e->e.getTagStateEur().equals(TccFbaBoxUpItemEnum.TagStateEur.YES.value)).count();
        //若子表对应的标签都打印，则更改主表的状态
        if(tagStateGoodsYes - itemList.size()==0){
            tccFbaBoxUp.setTagAllGoods(TccFbaBoxUpItemEnum.TagStateGoods.YES.value);
        }
        if(tagStateTransparentYes - itemList.size()==0){
            tccFbaBoxUp.setTagAllTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.YES.value);
        }
        if(tagStateEurYes - itemList.size()==0){
            tccFbaBoxUp.setTagAllEur(TccFbaBoxUpItemEnum.TagStateEur.YES.value);
        }

        //如果商品的透明标、欧代标 都无需打印，则状态不修改
		boolean isAllTransparentYes = false;
		boolean isAllEurYes = false;

		for(TccFbaBoxUpItem item:itemList){
			TccFbaPlanItem tccFbaPlanItem = new TccFbaPlanItem().setId(item.getFbaPlanItemId()).queryFirst();
			if(!tccFbaPlanItem.getIsSign().equals("否")|| checkUtil.isNullByObject(tccFbaPlanItem.getAnnexFile())){
				isAllTransparentYes = true;
			}
			if(item.getTagStateEur().equals(TccFbaBoxUpItemEnum.TagStateEur.YES.value)){
				TpAmazonShop tpAmazonShop = new TpAmazonShop().setId(tccFbaPlan.getShopId()).queryFirst();
				if( tpAmazonShop!=null && !(tpAmazonShop.getEuStatus()!=null && tpAmazonShop.getEuStatus()==0)){
					isAllEurYes = true;
				}
			}
		}
		if(!isAllTransparentYes){
			tccFbaBoxUp.setTagAllTransparent(TccFbaBoxUpItemEnum.TagStateTransparent.NOT.value);
		}
		if(!isAllEurYes){
			tccFbaBoxUp.setTagAllEur(TccFbaBoxUpItemEnum.TagStateEur.NOT.value);
		}



		tccFbaBoxUpMapper.update(tccFbaBoxUp);

        return R.ok();
	}

	/**
	 * 选择完方案后，修改方案选项标识符
	 */
	@Override
	public R updatePlacementOptionId(String planBid,String placementOptionId) throws Exception{
		storageMapper.updateFbaBoxUpInfoPlacementOptionId(planBid,placementOptionId);
		return R.ok();
	}


	/**
	 * 方案选择
	 * @param params 方案信息
	 */
	@Override
	public R yesChooseIdea(Map<String, Object> params) throws Exception{
		logger.info(ShiroUtils.getUserId()+"选择方案后参数："+params+"；");

		try {
			lock.lock(); // 加锁

			String bid = params.get("bid").toString();
			JSONObject dataPost = JSON.parseObject(params.get("dataPost").toString());
			if (dataPost.get("placementOptionId") == null){
				return R.error("placementOptionId未选择,不允许审核!");
			}
			String placementOptionId = dataPost.get("placementOptionId").toString();

			TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
			TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
			int apiCount = tccFbaBoxUp.getApiCount()!=null?tccFbaBoxUp.getApiCount():0;

			if(apiCount <= 0){
				//修改方案选项标识符
				updatePlacementOptionId(tccFbaBoxUp.getBidFbaPlan(),placementOptionId);
				apiCount ++;
			}
			lock.unlock(); // 释放锁

			if(apiCount <= 1){

				//先删除旧的
				storageMapper.delBoxUpInfoByPlanBid(tccFbaPlan.getBid());

				//按箱 - 自动 计划单与装箱单 一对一
				//填入FBAId
				List<TccFbaShipmentPreview> getShipmentList = getShipmentList(tccFbaPlan,placementOptionId);
				for(TccFbaShipmentPreview tccFbaShipmentPreview:getShipmentList){
					TccFbaBoxUpInfo addInfo = new TccFbaBoxUpInfo();
					addInfo.setFbaToken(null);
					addInfo.setFbaId(tccFbaShipmentPreview.getShipmentId());
					//填入FBA信息
					addInfo.setBoxUpBid(bid)//母表单号（TCC_FbaBoxUp）
							.setSearchIsShow(0)//查询页是否展示
							.setBidFbaPlan(tccFbaPlan.getBid())//计划单号
							.setStatus(1);
					tccFbaBoxUpInfoMapper.insert(addInfo);
				}

				int isAddFba =  new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaPlan.getBid()).count();
				if(isAddFba<=0){
					storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);
					return R.error("【设置放置选项】失败：FBA信息未新增成功") ;
				}

				//API
				//上传所选方案
				//请求api设置放置选项
				R apiRes1 = fbaInboundApiService.fbaBoxConfirmPlacementOption(tccFbaBoxUp,placementOptionId);
				if(apiRes1.getCode().equals(R.Code.FAILED.value)){
					storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);
					return R.error("【设置放置选项】失败："+apiRes1.getMsg()) ;
				}else{
					apiCount ++;
				}

			}

			if(apiCount <= 2){
				//获取运输选项与交付窗口
				R apiRes2 = fbaInboundApiService.generateTransportationAndDeliveryWindow(tccFbaBoxUp,placementOptionId);
				if(apiRes2.getCode().equals(R.Code.FAILED.value)){
					storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);
					return R.error("【获取运输选项与交付窗口】失败："+apiRes2.getMsg()) ;
				}else{
					//验证 运输选项与交付id 是否都获取到
					int updateCount = new TccFbaBoxUpInfo()
							.setBidFbaPlan(tccFbaPlan.getBid())
							.where("A.TransportationOptionId IS NULL OR A.DeliveryWindowOptionId IS NULL")
							.count();
					if(updateCount>0){
						storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);
						return R.error("【获取运输选项与交付窗口】失败：运输选项与交付信息未获取完全！") ;
					}else {
						apiCount ++;
					}
				}
			}

			if(apiCount <= 3){
				//设置交付窗口
				R apiRes3 = fbaInboundApiService.confirmDeliveryWindow(tccFbaBoxUp,placementOptionId);
				if(apiRes3.getCode().equals(R.Code.FAILED.value)){
					storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);
					return R.error("【设置交付窗口】失败："+apiRes3.getMsg()) ;
				}else {
					apiCount ++;
				}
			}

			if(apiCount <= 4){
				//设置运输选项
				R apiRes = fbaInboundApiService.confirmTransportation(tccFbaBoxUp,placementOptionId);
				if(apiRes.getCode().equals(R.Code.FAILED.value)){
					storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);
					return R.error("【设置运输选项】失败："+apiRes.getMsg()) ;
				}else {
					apiCount ++;
				}
			}

			storageMapper.updateBoxUpApiCount(tccFbaPlan.getBid(),apiCount);


			//修改成方案已确认
			storageMapper.updateBoxUpBoxStateByPlanBid(tccFbaPlan.getBid(),TccFbaBoxUpEnum.BoxState.YES_CHOOSE.value);

		}finally {
			try {
				lock.unlock(); // 确保释放锁
			}catch (Exception e){

			}
		}
		return R.ok();

	}


	/**
	 * 审核，自动 + 按箱
	 * dataPost 选择的方案JSON
	 * bid 装箱单号
	 * isReCountPurchaseAmount 是否重新计算采购价
	 */
	@Override
	//@Transactional
	public R doExamineByAutoAndBox(Map<String, Object> params) throws Exception{

		logger.info(ShiroUtils.getUserId()+"审核参数："+params+"；");
		String bid = params.get("bid").toString();
		TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(bid).queryFirst();
		TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();

		if (checkUtil.isNullByObject(tccFbaBoxUp.getPlacementOptionId())){
			return R.error("方案未确认,不允许审核!");
		}
		String placementOptionId = tccFbaBoxUp.getPlacementOptionId();

		//查询FBA，新增FBA信息
		//更新FBA
		R apiResByGetFbaInfo = fbaInboundApiService.reSearchShipments(bid,tccFbaPlan,placementOptionId);
		if(apiResByGetFbaInfo.getCode().equals(R.Code.FAILED.value)){
			return apiResByGetFbaInfo;
		}

		//T查询fbano，箱子数据，关联FBA和详情
		R apiResByGetBox = fbaInboundApiService.getListShipmentBoxesResponse(tccFbaPlan);
		if(apiResByGetBox.getCode().equals(R.Code.FAILED.value)){
			return apiResByGetBox;
		}

		//审核
		return examine(tccFbaBoxUp.getBidFbaPlan(),Integer.parseInt(params.get("isReCountPurchaseAmount").toString()));

	}



	public List<TccFbaShipmentPreview> getShipmentList(TccFbaPlan tccFbaPlan,String placementOptionId){
		List<TccFbaShipmentPreview> tccFbaShipmentPreviewList = new ArrayList<>();

		TccFbaInboundApiLog tccFbaInboundApiLog = new TccFbaInboundApiLog()
				//.setPid(tccFbaPlan.getId().toString())
				.setBid(tccFbaPlan.getBid())
				.setType("listPlacementOptions-"+tccFbaPlan.getGenerateNo())
				.queryFirst();
		if (tccFbaInboundApiLog != null){
			JSONObject resultJO = JSON.parseObject(tccFbaInboundApiLog.getJsonResult());
			JSONArray conditionJA = JSON.parseArray(resultJO.get("placementOptions").toString());

			for (int i = 0; i < conditionJA.size(); i++) {
				JSONObject JO = conditionJA.getJSONObject(i);
				JSONArray shipmentIds = JSON.parseArray(JO.get("shipmentIds").toString());
				JSONArray fees = JSON.parseArray(JO.get("fees").toString());
				//查询货件详情
				for (int j = 0; j < shipmentIds.size(); j++) {
					String  shipmentId = shipmentIds.get(j).toString();
					TccFbaInboundApiLog shipmentLog = new TccFbaInboundApiLog()
							.setPid(shipmentId)
							.setBid(tccFbaPlan.getBid())
							.setType("getShipment-"+tccFbaPlan.getGenerateNo())
							.queryFirst();
					if (shipmentLog == null){
						continue;
					}
					Shipment shipment = JSON.parseObject(shipmentLog.getJsonResult(), Shipment.class);
					if(shipment.getPlacementOptionId().equals(placementOptionId)){
						TccFbaShipmentPreview tccFbaShipmentPreview = new TccFbaShipmentPreview();
						tccFbaShipmentPreview.setShipmentId(shipment.getShipmentId());
						tccFbaShipmentPreviewList.add(tccFbaShipmentPreview);
					}
				}
			}
		}
		return tccFbaShipmentPreviewList;
	}






	/**
	 * 获取FBA导入（按箱） 页面子列表信息
	 * @param bid 单号
	 */
	@Override
	public List<Map<String, Object>> getFbaImportByBoxItenList(String bid) throws Exception{
		return new TccFbaBox()
				.addLeftJoin("TCC_FbaBoxRelevance B ON B.BoxId = A.Id")//关联信息表
				.addLeftJoin("TCC_FbaBoxUpInfo C ON C.Id = B.FbaBoxInfoId")//FBA信息表
				.addField("C.FbaNo fbaNo")//FBA编号
				.addField("C.FbaTrackNo fbaTrackNo")//FBA追踪编号
				.addField("C.FbaWarehouse fbaWarehouse")//FBA仓库
				.addField("C.FbaWarehouseAddr fbaWarehouseAddr")//FBA仓库地址
				.addField("C.FbaAmount fbaAmount")//FBA费用
				.setBidBoxUp(bid)
				.queryMap();
	}




	/**
	 * 获取修改FBA仓库页面子列表信息
	 * @param bid 单号
	 */
	@Override
	public List<Map<String, Object>> getFbaWarehouseItemList(String bid) throws Exception{
		return new TccFbaBoxUp()
				.addLeftJoin("TCC_FbaBoxUpInfo C ON C.BoxUpBid = A.Bid")//FBA信息表
				.addField("C.FbaNo fbaNo")//FBA编号
				.addField("C.FbaTrackNo fbaTrackNo")//FBA追踪编号
				.addField("C.FbaWarehouse fbaWarehouse")//FBA仓库
				.addField("C.FbaWarehouseAddr fbaWarehouseAddr")//FBA仓库地址
				.addField("C.FbaAmount fbaAmount")//FBA费用
				.setBid(bid)
				.queryMap();
	}




	/**
	 * 删除装箱单、自动按箱时的API返回的预览信息
	 * @param planBid 计划单号
	 */
	@Override
	public R delBoxUpAutoAndBoxApiPreviewInfo(String planBid,int generateNo) throws Exception{

		storageMapper.delBoxUpAutoAndBoxApiPreviewInfo(planBid,"generatePlacementOptions-"+generateNo,"getInboundOperationStatusPlacementOptions-"+generateNo,"listPlacementOptions-"+generateNo,"getShipment-"+generateNo);
		return  R.ok();
	}






}
